From 596f43c6d428d8da43a908b6e192fe77a010949b Mon Sep 17 00:00:00 2001 From: Mario Voigt Date: Tue, 14 Dec 2021 15:45:39 +0100 Subject: [PATCH] update --- .../box_maker_generic_generator.inx | 1 + .../box_maker_generic_generator.py | 843 +++++++++++++----- .../{inkscape_path.py => th_inkscape_path.py} | 23 + 3 files changed, 667 insertions(+), 200 deletions(-) rename extensions/fablabchemnitz/box_maker_generic_generator/{inkscape_path.py => th_inkscape_path.py} (92%) diff --git a/extensions/fablabchemnitz/box_maker_generic_generator/box_maker_generic_generator.inx b/extensions/fablabchemnitz/box_maker_generic_generator/box_maker_generic_generator.inx index 136bf6dc..cdbd9e32 100644 --- a/extensions/fablabchemnitz/box_maker_generic_generator/box_maker_generic_generator.inx +++ b/extensions/fablabchemnitz/box_maker_generic_generator/box_maker_generic_generator.inx @@ -46,6 +46,7 @@ 1 1 + 1 true diff --git a/extensions/fablabchemnitz/box_maker_generic_generator/box_maker_generic_generator.py b/extensions/fablabchemnitz/box_maker_generic_generator/box_maker_generic_generator.py index 6a743bfc..ad685f57 100644 --- a/extensions/fablabchemnitz/box_maker_generic_generator/box_maker_generic_generator.py +++ b/extensions/fablabchemnitz/box_maker_generic_generator/box_maker_generic_generator.py @@ -1,8 +1,12 @@ #!/usr/bin/env python3 + # We will use the inkex module with the predefined Effect base class. import inkex +# The simplestyle module provides functions for style parsing. + +import simplestyle import math -from inkscape_path import * +from th_inkscape_path import * from lxml import etree #Constants defined here @@ -11,9 +15,14 @@ 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 +RadiusSteelHingeAxis = 1.3 #Use axis about 2.6mm diameter, I use nails 2.3mmx70mm. The actual hole will be larger +RadiusSteelHingeAxisChange = 0.25 #Factor the the larger hole, multiplied by thickness MinMove = 1e-2 #Minimum distance betwwen two points (0.01 mm !) +SlidingLidSpaceZ = 1.3 #Space to allow easy move of the sliding lid (z or thickness). To be multiplied by thickness +SlidingLidSpaceX = 1.0 #Space to allow easy move in X direction/ + + #Global variables used for the whole program thickness = 0 burn = 0 @@ -54,6 +63,15 @@ def drawHole(path, x0, y0, dx, dy, burn): path.LineToVRel(-dy+burn) path.LineToHRel(-dx+burn) +# Generate vertical lines for flex +# Parameters : StartX, StartY, size, nunmber of lines and +1 if lines goes up and -1 down +def GenLinesFlex(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) + class Ellipse: ''' @@ -222,14 +240,6 @@ class Ellipse: 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): ''' @@ -290,29 +300,29 @@ class Ellipse: ''' 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) + GenLinesFlex(xpos, ypos, ShortMark, 1, 1, path) #Then nMark-1 long Lines - self.GenLinesFlex(xpos, ypos+ShortMark+2, LongMark, nMark-1, 1, path) + 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) + 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) + 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) + 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) + 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) + 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) + 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) + 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 @@ -335,14 +345,14 @@ class Ellipse: 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) + 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) + 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) + 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) + 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 @@ -352,29 +362,29 @@ class Ellipse: Now draw the pattern for the last notch ''' #Draw the edge line from Top to Bottom - self.GenLinesFlex(xpos, ypos, ShortMark, 1, 1, path) + GenLinesFlex(xpos, ypos, ShortMark, 1, 1, path) #Then nMark-1 long Lines - self.GenLinesFlex(xpos, ypos+ShortMark+2, LongMark, nMark-1, 1, path) + 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) + 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) + 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) + 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) + 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) + 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) + 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) + 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') @@ -392,37 +402,40 @@ class CornerPoint: 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) + #Compute position of circle center and corner according to corner quadrant and internal / external flags if position[0] <= thickness: #Left corner - self.xc = position[0] + self.radius + if x_internal: + self.xc = position[0] + self.radius + self.x_corner = position[0] + else: + self.xc = position[0] + self.radius - thickness + self.x_corner = position[0] - thickness else: #Right corner - self.xc = position[0] - self.radius + if x_internal: + self.xc = position[0] - self.radius + self.x_corner = position[0] + else: + self.xc = position[0] - self.radius + thickness + self.x_corner = position[0] + thickness if position[1] <= thickness: #Top corner - self.yc = position[1] + self.radius + if y_internal: + self.yc = position[1] + self.radius + self.y_corner = position[1] + else: + self.yc = position[1] + self.radius - thickness + self.y_corner = position[1] - thickness else: #Bottom corner - self.yc = position[1] - self.radius + if y_internal: + self.yc = position[1] - self.radius + self.y_corner = position[1] + else: + self.yc = position[1] - self.radius + thickness + self.y_corner = position[1] + thickness - #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 @@ -460,7 +473,7 @@ class CornerPoint: 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') + DebugMsg("End CornerPoint init. Corner="+str((self.x_corner, self.y_corner))+" Circle="+str((self.xc, self.yc, self.radius))+" 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): ''' @@ -468,6 +481,7 @@ class CornerPoint: 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) ''' + DebugMsg("Start drawCorner PathPos ="+str((path.x_noff, path.y_noff))+'\n') 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 @@ -484,8 +498,52 @@ class CornerPoint: 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) + nxc = self.xc + nyc = self.yc + if self.quadrant == 0: + #if needed, draw vertical line to cope with external corner + if self.y_internal == 0: + path.LineToVRel(-thickness) + DebugMsg("drawCorner, move dY="+str(-thickness)+"\n") + elif self.quadrant == 1: + #if needed, draw horizontal line to cope with external corner + if self.x_internal == 0: + path.LineToHRel(thickness) + DebugMsg("drawCorner, move dX="+str(thickness)+"\n") + elif self.quadrant == 2: + #if needed, draw vertical line to cope with external corner + if self.y_internal == 0: + path.LineToVRel(thickness) + DebugMsg("drawCorner, move dY="+str(thickness)+"\n") + elif self.quadrant == 3: + #if needed, draw horizontal line to cope with external corner + if self.x_internal == 0: + path.LineToHRel(-thickness) + DebugMsg("drawCorner, move dX="+str(-thickness)+"\n") + DebugMsg("drawCorner before circle PathPos ="+str((path.x_noff, path.y_noff))+'\n') + DebugMsg("drawCorner radius Center"+str((nxc, nyc))+" Radius="+str(self.radius)+ " quadrant="+str(self.quadrant)+'\n') + path.drawQuarterCircle(nxc, nyc, self.radius, self.quadrant) + DebugMsg("drawCorner after circle PathPos ="+str((path.x_noff, path.y_noff))+'\n') + if self.quadrant == 0: + #if needed, draw H line to cope with external corner + if self.x_internal == 0: + path.LineToHRel(thickness) + DebugMsg("drawCorner, move dX="+str(thickness)+"\n") + elif self.quadrant == 1: + #if needed, draw V line to cope with external corner + if self.y_internal == 0: + path.LineToVRel(thickness) + DebugMsg("drawCorner, move dY="+str(thickness)+"\n") + elif self.quadrant == 2: + #if needed, draw H line to cope with external corner + if self.x_internal == 0: + path.LineToHRel(-thickness) + DebugMsg("drawCorner, move dX="+str(-thickness)+"\n") + elif self.quadrant == 3: + #if needed, draw V line to cope with external corner + if self.y_internal == 0: + path.LineToVRel(-thickness) + DebugMsg("drawCorner, move dY="+str(-thickness)+"\n") 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: @@ -494,6 +552,8 @@ class CornerPoint: 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) + DebugMsg("End drawCorner PathPos ="+str((path.x_noff, path.y_noff))+'\n') + class NotchLine: @@ -524,6 +584,8 @@ class NotchLine: # 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)) + # Round size to avoid float errors + size = round(size, 3) # Compute number of joints if finger_joint_size == 0: # No finger joint self.nb_finger_joint = 0 @@ -571,21 +633,23 @@ class NotchLine: 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) + self.start_line_joint_y = self.StartY - 0.5*finger_joint_size*math.sin(angle) + DebugMsg("NotchLine Init, DrawHalf=1, start_line_joint = "+str((self.start_line_joint_x, self.start_line_joint_y))+" nb_joint="+str(self.nb_finger_joint)+" EndStatus="+str(self.EndStatus)+'\n') + if (self.nb_finger_joint%2) == 0: + if 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 @@ -714,13 +778,14 @@ class NotchLine: #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 + DeltaBurn = -burn else: AngleJoint = self.Angle + math.pi/2 - DeltaBurn = -burn + 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 + DebugMsg("Position before drawNotchLine : "+str((path.x_noff, path.y_noff))+'\n') 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) @@ -1109,7 +1174,8 @@ class FlexFace: sizeclips = 18 nbclips = int(zoneclips // sizeclips) if nbclips == 0: - inkex.errormsg('Box is not high enough, no rrom for clips') + inkex.errormsg('Box is not high enough, no room for clips') + CloseDebugFile() return DebugMsg("\ndrawRoundedFlexFace, sizeclips="+str(sizeclips)+" nbclips="+str(nbclips)+'\n') ListFlexLines = [] @@ -1121,11 +1187,13 @@ class FlexFace: 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 + DebugMsg("Start Point is "+str((self.path.x_noff, self.path.y_noff))+'\n') 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 + DebugMsg("Start Point is "+str((self.path.x_noff, self.path.y_noff))+'\n') First_hLine.drawNotchLine(self.path) xpos = (FlexElement[0]-FlexElement[2]-LastRadius)/2 - DebugMsg("After drawing first half of notch line, xpos ="+str(xpos)+'\n') + DebugMsg("After drawing first half of notch line, pos ="+str((self.path.x_noff, self.path.y_noff))+'\n') ListFlexLines.append((xpos, FlexElement[2])) #Add this position to draw flex lines. #Then the line corresponding to rounded corner if FlexElement[2] > 0: @@ -1353,7 +1421,7 @@ class BoxFace: #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') + 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') @@ -1441,10 +1509,17 @@ class BoxFace: 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): + def drawFaceWithHoles(self, n_slot, slot_size, DeltaHolePosition, z_joint_size, Height_percentage, 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) + n_slot : number of slots + slot_size + DeltaHolePosition : Offset for holes + z_joint_size + Height_percentage : Actual interior will be height*percentage, so dig holes only for useful part + ClosePath : + HingeList : ''' if HingeList == None: #No cut for hinge, call regular function to draw face @@ -1453,7 +1528,8 @@ class BoxFace: 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) + InteriorHeight = self.bottom_right_corner.y_end_joint * Height_percentage / 100.0 + l_NotchLine = NotchLine((0, 0, 1), (InteriorHeight, 0, 1), math.pi/2, z_joint_size) StartHole = l_NotchLine.start_line_joint_y + l_NotchLine.JointSize Spacing = 2*l_NotchLine.JointSize @@ -1469,6 +1545,159 @@ class BoxFace: self.path.Close() self.path.GenPath() + def drawFaceInternalSlidingLeft(self, ClosePath): + ''' + Draw specific pattern helping the sliding of the lid inside the box + ''' + radius_back = self.top_left_corner.radius + # Go To starting point (top left) + self.path.MoveTo(self.top_left_corner.x_corner, self.top_left_corner.y_corner+thickness) + DebugMsg("drawFaceInternalSlidingLeft, top left start in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Then draw the small quarter of circle + self.path.LineToVRel(radius_back) + DebugMsg("drawFaceInternalSlidingLeft, now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + self.path.drawQuarterCircle(self.top_left_corner.x_corner+radius_back, self.top_left_corner.y_corner+radius_back+thickness, radius_back, 0) + DebugMsg("drawFaceInternalSlidingLeft, after circle in "+str((self.path.x_noff, self.path.y_noff))+'\n') + self.path.LineToHRel(-radius_back) + DebugMsg("drawFaceInternalSlidingLeft, End of top left circle in "+str((self.path.x_noff, self.path.y_noff))+'\n') + + + #Then restart path at bottom right + self.path.MoveTo(self.bottom_right_corner.x_end_joint, self.bottom_right_corner.y_end_joint) + DebugMsg("drawFaceInternalSlidingLeft, start in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Draw the horizontal line towards left corner + self.path.LineTo(self.bottom_left_corner.x_end_joint+SlidingLidSpaceZ*thickness, self.bottom_left_corner.y_end_joint) + DebugMsg("drawFaceInternalSlidingLeft, now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Draw the vertical left line towards rounded back + #Change left line + x = self.path.x_noff + self.LeftLine = NotchLine((x, self.bottom_left_corner.y_start_joint, 0), (x, self.top_left_corner.y_end_joint+SlidingLidSpaceZ*thickness, 0), -math.pi/2, self.LeftLine.JointSize) + self.LeftLine.drawNotchLine(self.path) + x = self.top_left_corner.x_end_joint+SlidingLidSpaceZ*thickness + y = self.top_left_corner.y_end_joint+SlidingLidSpaceZ*thickness + DebugMsg("drawFaceInternalSlidingLeft, after notches in "+str((self.path.x_noff, self.path.y_noff))+'\n') + self.path.LineTo(x, y) + DebugMsg("drawFaceInternalSlidingLeft, now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Draw the quarter circle (quadrant 0) + self.path.drawQuarterCircle(x+radius_back, y, radius_back, 0) + DebugMsg("drawFaceInternalSlidingLeft, after first circle in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Then the horizontal line towards the large circle + x = self.top_right_corner.x_end_joint - (SlidingLidSpaceZ+1)*thickness + y = self.path.y_noff + self.path.LineTo(x, y) + DebugMsg("drawFaceInternalSlidingLeft, now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #then large circle (Quadrant 1) + radius = self.top_right_corner.radius + y_end = min(self.top_right_corner.y_start_joint, self.bottom_right_corner.y_end_joint - thickness) + self.path.Bezier(x+radius*0.551916, y, x + radius, y+radius*(1-0.551916), x+radius, y_end) + DebugMsg("drawFaceInternalSlidingLeft, now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Then V Line up to bottom + self.path.LineTo(self.bottom_right_corner.x_end_joint- (SlidingLidSpaceZ+1)*thickness, self.bottom_right_corner.y_end_joint - thickness) + DebugMsg("drawFaceInternalSlidingLeft, After V Line now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Then H line + x = self.bottom_right_corner.x_end_joint - thickness + y = self.bottom_right_corner.y_end_joint - thickness + self.path.LineTo(x, y) + DebugMsg("drawFaceInternalSlidingLeft, now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Then V Line + self.path.LineTo(x, y_end) + #Then large circle, first quadrant but reverse drawing + self.path.Bezier(x, y_end - radius*0.551916, x - radius*0.551916, y_end-radius, x-radius+thickness, y_end-radius) # upper right quarter + DebugMsg("drawFaceInternalSlidingLeft, After circle 2 in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Then V line + self.path.LineToVRel(-thickness) + DebugMsg("drawFaceInternalSlidingLeft, now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #And last large circle + x = self.path.x_noff + y = self.path.y_noff + self.path.Bezier(x+radius*0.551916, y, self.bottom_right_corner.x_end_joint, y+radius*(1-0.551916), self.bottom_right_corner.x_end_joint, self.top_right_corner.y_start_joint-thickness) + DebugMsg("drawFaceInternalSlidingLeft, now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + + #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 drawFaceInternalSlidingRight(self, ClosePath): + ''' + Draw specific pattern helping the sliding of the lid inside the box + ''' + radius_back = self.top_right_corner.radius + # Go To starting point (top Right) + self.path.MoveTo(self.top_right_corner.x_corner, self.top_right_corner.y_corner+thickness) + DebugMsg("drawFaceInternalSlidingRight, top right start in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Then draw the small quarter of circle + self.path.LineToHRel(-radius_back) + DebugMsg("drawFaceInternalSlidingRight, now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + self.path.drawQuarterCircle(self.top_right_corner.x_corner-radius_back, self.top_right_corner.y_corner+radius_back+thickness, radius_back, 1) + DebugMsg("drawFaceInternalSlidingRight, after circle in "+str((self.path.x_noff, self.path.y_noff))+'\n') + self.path.LineToVRel(-radius_back) + DebugMsg("drawFaceInternalSlidingRight, End of top right circle in "+str((self.path.x_noff, self.path.y_noff))+'\n') + + + #Then restart path at bottom left + self.path.MoveTo(self.bottom_left_corner.x_end_joint, self.bottom_left_corner.y_end_joint) + DebugMsg("drawFaceInternalSlidingRight, start in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Draw the horizontal line towards right corner + self.path.LineTo(self.bottom_right_corner.x_end_joint-SlidingLidSpaceZ*thickness, self.bottom_right_corner.y_end_joint) + DebugMsg("drawFaceInternalSlidingRight, now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Draw the vertical Right line towards rounded back + #Change right line + x = self.path.x_noff + self.RightLine = NotchLine((x, self.bottom_right_corner.y_start_joint, 1), (x, self.top_right_corner.y_start_joint+SlidingLidSpaceZ*thickness, 1), -math.pi/2, self.RightLine.JointSize) + self.RightLine.drawNotchLine(self.path) + DebugMsg("drawFaceInternalSlidingRight, after notches in "+str((self.path.x_noff, self.path.y_noff))+'\n') + y = self.top_right_corner.y_start_joint+SlidingLidSpaceZ*thickness + self.path.LineTo(x, y) + DebugMsg("drawFaceInternalSlidingRight, now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Draw the quarter circle, use bezier instead of drawCircle because reverse draw + self.path.Bezier(x, y - radius_back*0.551916, x - radius_back*(1-0.551916), y-radius_back, x-radius_back, y-radius_back) + DebugMsg("drawFaceInternalSlidingRight, after first circle in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Then the horizontal line towards the large circle + x = self.top_left_corner.x_start_joint + (SlidingLidSpaceZ+1)*thickness + y = self.path.y_noff + self.path.LineTo(x, y) + DebugMsg("drawFaceInternalSlidingRight, now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #then large circle (Quadrant 0) + radius = self.top_left_corner.radius + y_end = min(self.top_left_corner.y_end_joint, self.bottom_left_corner.y_end_joint - thickness) + self.path.Bezier(x-radius*0.551916, y, x - radius, y+radius*(1-0.551916), x-radius, y_end) + x = x-radius + DebugMsg("drawFaceInternalSlidingRight, after circle 1 in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Then V Line up to bottom + self.path.LineTo(x, self.bottom_left_corner.y_end_joint - thickness) + DebugMsg("drawFaceInternalSlidingLeft, After V Line now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Then H line + x = self.bottom_left_corner.x_end_joint + thickness + y = self.bottom_left_corner.y_end_joint - thickness + self.path.LineTo(x, y) + DebugMsg("drawFaceInternalSlidingRight, now in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Then Up yo y_end + self.path.LineTo(x, y_end) + #Then large circle, first quadrant + self.path.Bezier(x, y_end - radius*0.551916, x + radius*0.551916, y_end-radius, x+radius-thickness, y_end-radius) + DebugMsg("drawFaceInternalSlidingRight, Circle in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Then V line + self.path.LineToVRel(-thickness) + DebugMsg("drawFaceInternalSlidingRight, VLine in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #And last large circle + x = self.path.x_noff + y = self.path.y_noff + self.path.Bezier(x-radius*0.551916, y, self.bottom_left_corner.x_end_joint, y+radius*(1-0.551916), self.bottom_left_corner.x_end_joint, self.top_left_corner.y_end_joint-thickness) + DebugMsg("drawFaceInternalSlidingRight, Circle in "+str((self.path.x_noff, self.path.y_noff))+'\n') + #Then Last line + self.path.LineTo(self.bottom_left_corner.x_end_joint, self.bottom_left_corner.y_end_joint) + #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 drawSideLineNotches(self, xpos, ypos): ''' Draw the side line notches used with sliding lid. These lines are on left and right lines @@ -1827,7 +2056,7 @@ class BoxFace: -class BoxMakerGenericGenerator(inkex.Effect): +class GenericBox(inkex.Effect): """ Creates a new layer with the drawings for a parametrically generated box. """ @@ -1858,6 +2087,10 @@ class BoxMakerGenericGenerator(inkex.Effect): type = int, dest = 'n_slot_y', default = '2', help = 'Number of rows of slots') + self.arg_parser.add_argument('--h_slot', action = 'store', + type = int, dest = 'h_slot', default = '100', + help = 'Height of slots (%)') + self.arg_parser.add_argument('--z', action = 'store', type = float, dest = 'z', default = '40.0', help = "box height") @@ -1882,6 +2115,10 @@ class BoxMakerGenericGenerator(inkex.Effect): type = inkex.Boolean, dest = 'SkipFlexLines', default = 'true', help = 'Skip flex lines when possible') + self.arg_parser.add_argument('--radius_lid', action = 'store', + type = float, dest = 'radius_lid', default = '50.0', + help = 'Radius of rounded lid') + self.arg_parser.add_argument('--burn', action = 'store', type = float, dest = 'burn', default = '0.1', help = 'laser burn size') @@ -1961,20 +2198,34 @@ class BoxMakerGenericGenerator(inkex.Effect): #Small size, only one notch i_notch_number = 1 notch_size = size_slot / 3 # Notch is center aligned - elif size_slot < 80: + elif size_slot < 50: #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 + elif size_slot < 120: + #Medium high 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) + elif size_slot < 200: + #Medium high size, draw 20mm notches + notch_number = size_slot / 20 + 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 30mm notches + notch_number = size_slot / 30 + 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): @@ -1991,10 +2242,12 @@ class BoxMakerGenericGenerator(inkex.Effect): 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') + CloseDebugFile() 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') + CloseDebugFile() exit() if x <= 100: basic_size_x = 5.0 @@ -2052,7 +2305,9 @@ class BoxMakerGenericGenerator(inkex.Effect): 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) + #Change the diameter to allow some space + locRadiusSteelHingeAxis = RadiusSteelHingeAxis + thickness * RadiusSteelHingeAxisChange + path.drawCircle(0, 4.5*thickness, locRadiusSteelHingeAxis) path.Close() path.GenPath() if path.xmin < self.BoundingBox[0]: @@ -2068,11 +2323,11 @@ class BoxMakerGenericGenerator(inkex.Effect): ''' Draw the top of the box. It depends on the lid style ''' - if self.options.lid_type == 'Without': + if self.options.lid_type == 'Without' or self.options.lid_type == 'Coffin': 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 + #Not compatible with rounded corners on 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 @@ -2097,35 +2352,53 @@ class BoxMakerGenericGenerator(inkex.Effect): 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) + if self.options.lid_type == 'SlidingRounded': + #Specific case, top is a rectangle which is xbox long and ytop_sliding_rounded wide with finger joints on 3 edges + #The rectangle is a little bit bigger than thickness to allow easy handling. + TopLine = BoxFace('Lid_Joints', CornerPoint((thickness,0), 0, 1, 1), + 0, CornerPoint((xbox-thickness-SlidingLidSpaceX,0), 0, 1, 1), + 0, CornerPoint((xbox-thickness-SlidingLidSpaceX,thickness*1.5), 0, 1, 1), + self.x_joint, CornerPoint((thickness,thickness*1.5), 0, 1, 1), + 0, self.group, [0.0,0.0]) + TopLine.drawSimpleFace(True) + self.UpdateBoundingBox(TopLine) + Top = BoxFace('Top', CornerPoint((0,0), 0, 1, 1), + self.x_joint, CornerPoint((xbox,0), 0, 1, 1), + self.y_joint, CornerPoint((xbox, self.ytop_sliding_rounded), 0, 1, 1), + 0, CornerPoint((0, self.ytop_sliding_rounded), 0, 1, 1), + self.y_joint, self.group, [-thickness,-self.BoundingBox[3]]) + Top.drawSimpleFace(True) 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 + + #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): ''' @@ -2133,7 +2406,15 @@ class BoxMakerGenericGenerator(inkex.Effect): 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), + if self.options.lid_type == 'SlidingRounded': + 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), + 0, 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 + + else: + 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), @@ -2161,40 +2442,41 @@ class BoxMakerGenericGenerator(inkex.Effect): self.UpdateBoundingBox(Bottom) return - def drawColumWall(self, index, n_slot_y, y_slot_size, ListNotchPos, length, zbox, xOffset, yOffset, parent): + def drawColumWall(self, index, n_slot_y, y_slot_size, ListNotchPos, length, zbox, height_percentage, xOffset, yOffset, parent): ''' Draw the face, specific case for columns walls This is a specific face with cuts for row walls on top ''' - DebugMsg("\nDrawColumWall, 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') + DebugMsg("\nDrawColumWall, index="+str(index)+" n_Slot="+str(n_slot_y)+" Slot_Size="+str(y_slot_size)+" Length="+str(length)+" Height="+str(zbox)+" Percentage="+str(height_percentage)+" 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 + actual_height = zbox * height_percentage / 100.0 + VNotchLine1 = NotchLine((length,0,1), (length, actual_height, 1), math.pi/2, self.z_joint ) #Vertical Notch line + VNotchLine2 = NotchLine((0,actual_height,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.LineToVRel(actual_height/2) path.LineToHRel(thickness) - path.LineToVRel(-zbox/2) + path.LineToVRel(-actual_height/2) path.LineTo(length, 0) #Second line (V), this is a notch line path.LineTo(length, thickness) VNotchLine1.drawNotchLine(path) - path.LineTo(length, zbox) + path.LineTo(length, actual_height) #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.LineTo(Notch[0]+Notch[1], actual_height) path.LineToVRel(thickness) path.LineToHRel(-Notch[1]) path.LineToVRel(-thickness) - path.LineTo(0, zbox) + path.LineTo(0, actual_height) #and last one - path.LineTo(0, zbox-thickness) + path.LineTo(0, actual_height-thickness) VNotchLine2.drawNotchLine(path) path.LineTo(0, 0) @@ -2215,44 +2497,49 @@ class BoxMakerGenericGenerator(inkex.Effect): #DebugMsg("Closing path, BoundingBox="+str(self.BoundingBox)+'\n') - def drawRowWall(self, index, n_slot_x, x_slot_size, ListNotchPos, length, zbox, xOffset, yOffset, parent): + def drawRowWall(self, index, n_slot_x, x_slot_size, ListNotchPos, length, zbox, height_percentage, xOffset, yOffset, parent): ''' Draw the face, specific case for row walls This is a specific face with cuts for columns walls on bottom + index : index of Row wall (0..nSlot-1) + n_slot_x : number of slots (columns) to draw specific cuts for the column wall + x_slot_size + ListNotchPos : Position of notches ''' DebugMsg("\nDrawRowWall, 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)) + actual_height = zbox * height_percentage / 100.0 - 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 + VNotchLine1 = NotchLine((length,0,1), (length, actual_height, 1), math.pi/2, self.z_joint ) #Vertical Notch line + VNotchLine2 = NotchLine((0,actual_height,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 + #first H line (top) without cut, 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 + path.LineTo(length, actual_height) + #Third line (bottom 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) + if group_num != Notch[2]: # Change of group, draw cut (up to half of the piece) + path.LineTo(group_num * (x_slot_size + thickness) , actual_height) + path.LineToVRel(-actual_height/2) path.LineToHRel(-thickness) - path.LineToVRel(zbox/2) + path.LineToVRel(actual_height/2) group_num = Notch[2] #Change group for next pass - path.LineTo(Notch[0]+Notch[1], zbox) + path.LineTo(Notch[0]+Notch[1], actual_height) path.LineToVRel(thickness) path.LineToHRel(-Notch[1]) path.LineToVRel(-thickness) - path.LineTo(0, zbox) + path.LineTo(0, actual_height) #and last one - path.LineTo(0, zbox-thickness) + path.LineTo(0, actual_height-thickness) VNotchLine2.drawNotchLine(path) path.LineTo(0, 0) @@ -2392,7 +2679,76 @@ class BoxMakerGenericGenerator(inkex.Effect): if path.ymax > self.BoundingBox[3] - 2: self.BoundingBox[3] = path.ymax + 2 path.GenPath() + + def drawRoundedSlidindLid(self, w_lid, l_lid, xOffset, yOffset, parent): + ''' + Draw the rounded sliding lid. + This is a rectangle made of flex which is w_lid wide and l_lid long. + There are notches on one width long edge, but not on the other edges + ''' + DebugMsg("\ndrawRoundedSlidindLid, w_lid="+str(w_lid)+" l_lid="+str(l_lid)+'\n') + #Change offset in y direction because this one will be drawn from bottom left. + path = th_inkscape_path((xOffset, yOffset - thickness), parent, 'Sliding_Top') + DebugMsg("Offset ="+str((xOffset, yOffset))+" Path_Offset="+str((path.offsetX, path.offsetY))+'\n') + + #First build the notch line for the rectangle + NotchLine1 = NotchLine((0, w_lid-thickness, 0), (0, thickness, 0), -math.pi/2, self.z_joint ) #Vertical Notch line, left edge, external + #Then draw the rectangle + path.MoveTo(0, w_lid-thickness) + NotchLine1.drawNotchLine(path) + DebugMsg("After Notches pos="+str((path.x_noff, path.y_noff))+'\n') + path.LineToHRel(thickness) + path.LineToVRel(-thickness) + #Then the top H Line + path.LineTo(l_lid, 0) + #Then V Line + path.LineToVRel(w_lid) + #Then last H line + path.LineTo(thickness, w_lid) + path.LineToVRel(-thickness) + path.LineTo(0, w_lid-thickness) + #Now draw flex lines, first compute flex parameters + nLines = int(l_lid - thickness) - 1 #One mm free at each end + delta_x = (l_lid - thickness - 1)/nLines + TotalHeight = w_lid + 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("\ndrawRoundedSlidindLid, nLines="+str(nLines)+" TotalHeight="+str(TotalHeight)+" nMark="+str(nMark)+" LongMark="+str(LongMark)+" ShortMark="+str(ShortMark)+'\n') + xpos = thickness + 1 + ypos = 0 + for i in range(nLines): + if i % 2 == 0: + #Even number, start with short mark and draw from top to bottom + GenLinesFlex(xpos, 0, ShortMark, 1, 1, path) + #Then nMark-1 long Lines + GenLinesFlex(xpos, ShortMark+2, LongMark, nMark-1, 1, path) + #And the last short line + GenLinesFlex(xpos, TotalHeight-ShortMark, ShortMark, 1, 1, path) + else: + #odd number draw long lines only, at 1mm from edge + GenLinesFlex(xpos, w_lid-1, LongMark, nMark, -1, path) + xpos += delta_x + + + + #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 @@ -2420,6 +2776,7 @@ class BoxMakerGenericGenerator(inkex.Effect): 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) + radius_lid = self.svg.unittouu(str(self.options.radius_lid) + unit) if self.options.StraigthCorners: back_left_radius = 0 @@ -2442,12 +2799,16 @@ class BoxMakerGenericGenerator(inkex.Effect): 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)) + CloseDebugFile() 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)) + CloseDebugFile() exit() @@ -2494,9 +2855,34 @@ class BoxMakerGenericGenerator(inkex.Effect): 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') + CloseDebugFile() exit() self.front_joint = 0 #No joint on front top + # If lid is rounded sliding, there are always internal walls left and right + if self.options.lid_type == 'SlidingRounded': + if radius_lid > zbox or radius_lid > ybox: + inkex.errormsg('Error: incorrect radius for sliding lid, should be lower than width and height ') + CloseDebugFile() + exit() + 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 or front_left_radius > 0 or front_right_radius: + inkex.errormsg('Error: Sliding lid is incompatible with rounded corners') + CloseDebugFile() + exit() + self.front_joint = 0 #No joint on front top + #Check that the dimensions are OK. y_box should be greater than radius_lid*pi/2 + self.radius_back_lid = thickness * 6 + self.ytop_sliding_rounded = ybox - radius_lid + self.length_sliding_rounded = zbox + radius_lid*(math.pi/2 - 1) + DebugMsg("Rounded sliding, radius_lid="+str(radius_lid)+", radius_back_lid="+str(self.radius_back_lid)+" ytop_sliding_rounded="+str(self.ytop_sliding_rounded)+" length_sliding_rounded="+str(self.length_sliding_rounded)+"\n") + if self.length_sliding_rounded > zbox + self.radius_back_lid*(math.pi/2 - 2) + self.ytop_sliding_rounded - 2 * thickness: + inkex.errormsg('Error: no room for sliding lid, please increase width, should be at least '+str( (radius_lid - self.radius_back_lid)*(math.pi/2 - 1) + 2 * thickness + radius_lid + self.radius_back_lid )) + CloseDebugFile() + exit() + # If there is no lid, no notches on top if self.options.lid_type == 'Without': self.front_joint = 0 #No joint on front top @@ -2534,10 +2920,19 @@ class BoxMakerGenericGenerator(inkex.Effect): 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') + CloseDebugFile() 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) + HingePos = (self.x_slot_size - hingeWidth)/2.0 + self.HingeList.append((0, HingePos, HingePos)) # One hinge, starting at the middle of slot 0 (the only one) + elif self.n_slot_x == 1: + #One slot, but a large one. 2 hinges about 1/4 - 3/4 of the edge + HingePos = max(self.x_slot_size/4 - hingeWidth/2, 2) + if HingePos < 10: + HingePos = 10 + self.HingeList.append((0, HingePos, HingePos)) + self.HingeList.append((0, self.x_slot_size - HingePos, (self.x_slot_size - HingePos - hingeWidth) )) 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 @@ -2558,35 +2953,37 @@ class BoxMakerGenericGenerator(inkex.Effect): 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") + DebugMsg("Hinge width="+str(hingeWidth)+", Number of hinges="+str(len(self.HingeList))+", Hinge pos="+str(self.HingeList)+"\n") - #Draw external faces which are planes, begin with top + #Draw external faces which are planes, begin with top (no top for rounded sliding or open or coffin) + DebugMsg("\n\nBuild TOP\n") self.BuildTop(xbox, ybox, back_left_radius, back_right_radius, front_right_radius, front_left_radius) + DebugMsg("\n\nBuild Bottom\n") 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 + 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 @@ -2597,7 +2994,7 @@ class BoxMakerGenericGenerator(inkex.Effect): LidFace = None if front_left_radius == 0 and front_right_radius == 0: if HasLid: - DebugMsg("Draw font lid\n") + DebugMsg("Draw front 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), @@ -2606,17 +3003,18 @@ class BoxMakerGenericGenerator(inkex.Effect): LidFace.drawSimpleFace(True) self.UpdateBoundingBox(LidFace) #Now update bounding box, to place back face just below yposface = -self.BoundingBox[3] - DebugMsg("\nStraight 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 + if self.options.lid_type != 'SlidingRounded': + DebugMsg("\nStraight 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 @@ -2742,19 +3140,26 @@ class BoxMakerGenericGenerator(inkex.Effect): # No round for left face # Left is ybox * zbox, corners are external in y but internal in x DebugMsg("\nStraight face for Left\n") - if self.options.lid_type == 'Sliding': + if self.options.lid_type == 'Sliding' or self.options.lid_type == 'SlidingRounded' : 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 + if self.options.lid_type == 'SlidingRounded': + LeftFace = BoxFace('Left', CornerPoint((0,0), 0, 1, 0, 0), + self.y_joint, CornerPoint((ybox,0), radius_lid, 1, 0), + 0, 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 + else: + 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 + LeftFace.drawSideLineNotches(xpos, yposface) #Left face is straight xpos = -LeftFace.BoundingBox[2]-2 elif back_left_radius == 0: #Rounded corner on Front left @@ -2803,15 +3208,22 @@ class BoxMakerGenericGenerator(inkex.Effect): # Right is ybox * zbox, corners are external in y but internal in x DebugMsg("\nStraight face for Right\n") - if self.options.lid_type == 'Sliding': + if self.options.lid_type == 'Sliding' or self.options.lid_type == 'SlidingRounded': 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 + if self.options.lid_type == 'SlidingRounded': + RightFace = BoxFace('Right', CornerPoint((0,0), radius_lid, 1, 0), + self.y_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), + 0, self.group, [xpos, yposface-delta_yposface]) #Draw face just right from previous drawings + else: + 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 @@ -2847,6 +3259,7 @@ class BoxMakerGenericGenerator(inkex.Effect): 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 + DebugMsg("\n\nFlex on all faces\n") 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 @@ -2922,9 +3335,9 @@ class BoxMakerGenericGenerator(inkex.Effect): 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) + InternalBack.drawFaceWithHoles(self.n_slot_x, self.x_slot_size, d1 - thickness, self.z_joint, self.options.h_slot, True, self.HingeList) else: - InternalBack.drawFaceWithHoles(self.n_slot_x, self.x_slot_size, d1 - thickness, self.z_joint, True) + InternalBack.drawFaceWithHoles(self.n_slot_x, self.x_slot_size, d1 - thickness, self.z_joint, self.options.h_slot, True) xpos = -InternalBack.BoundingBox[2]-2 @@ -2952,7 +3365,7 @@ class BoxMakerGenericGenerator(inkex.Effect): 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) + InternalFront.drawFaceWithHoles(self.n_slot_x, self.x_slot_size, d1 - thickness, self.z_joint, self.options.h_slot, True) xpos = -InternalFront.BoundingBox[2]-2 # Then Left and right internal walls if needed. @@ -2976,13 +3389,20 @@ class BoxMakerGenericGenerator(inkex.Effect): 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) + if self.options.lid_type == 'SlidingRounded': + InternalLeft = BoxFace('Int_Left', CornerPoint((0,0), self.radius_back_lid, 1, 0), #First corner, internal x, external y + 0, CornerPoint((ybox,0), radius_lid, 1, 0), + 0, CornerPoint((ybox, zbox), 0, 1, 1), #internal both directions + 0, CornerPoint((0,zbox), 0, 1, 1), + self.z_joint, self.group, [xpos, ypos]) #Draw face just below previous drawings + InternalLeft.drawFaceInternalSlidingLeft(True) #Left side + else: + 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, self.options.h_slot, True) xpos = -InternalLeft.BoundingBox[2]-2 @@ -3005,26 +3425,48 @@ class BoxMakerGenericGenerator(inkex.Effect): else: d2 = thickness DebugMsg("\nDrawing Internal Right\n") - InternalRight = BoxFace('Int_Right', CornerPoint((0,0), 0, 1, 1), #First corner, internal on both sides + if self.options.lid_type == 'SlidingRounded': + InternalRight = BoxFace('Int_Right', CornerPoint((0,0), radius_lid, 1, 0), #First corner, internal x, external y + 0, CornerPoint((ybox,0), self.radius_back_lid, 1, 0), + self.z_joint, CornerPoint((ybox, zbox), 0, 1, 1), #internal both directions + 0, CornerPoint((0,zbox), 0, 1, 1), + 0, self.group, [xpos, ypos]) #Draw face just below previous drawings + InternalRight.drawFaceInternalSlidingRight(True) #Right side + else: + 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) + InternalRight.drawFaceWithHoles(self.n_slot_y, self.y_slot_size, d1 - thickness, self.z_joint, self.options.h_slot, True) + xpos = -InternalRight.BoundingBox[2]-2 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 - - + + if self.options.lid_type == 'SlidingRounded': + #Draw the internal wall at the back used to "protect" the sliding lid inside the box + InternalProtection = BoxFace('Int_Back', CornerPoint((0,0), 0, 1, 1), #First corner, internal x, internal y + 0, CornerPoint((xbox-2*thickness,0), 0, 1, 1), + self.z_joint, CornerPoint((xbox-2*thickness, zbox-self.radius_back_lid-thickness), 0, 1, 1), #internal both directions + 0, CornerPoint((0,zbox-self.radius_back_lid-thickness), 0, 1, 1), + self.z_joint, self.group, [xpos, ypos]) #Draw face just below previous drawings + InternalProtection.drawSimpleFace(True) + self.UpdateBoundingBox(InternalProtection) #Now update bounding box + ypos = -self.BoundingBox[3] + xpos = 0.0 + #And draw the sliding lid + self.drawRoundedSlidindLid(xbox-SlidingLidSpaceX, self.length_sliding_rounded, xpos, ypos, self.group) + #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) + self.drawColumWall(i, self.n_slot_y, self.y_slot_size, self.ListNotchColumns, ybox-2*thickness, zbox_internal_walls, self.options.h_slot, xpos, ypos, self.group) xpos -= ybox + 2 #Next position for drawing #Then rows, nearly the same, but opening at the bottom edge @@ -3032,7 +3474,7 @@ class BoxMakerGenericGenerator(inkex.Effect): 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) + self.drawRowWall(i, self.n_slot_x, self.x_slot_size, self.ListNotchRows, xbox-2*thickness, zbox_internal_walls, self.options.h_slot, xpos, ypos, self.group) xpos -= xbox + 2 #Next position for drawing # @@ -3052,5 +3494,6 @@ class BoxMakerGenericGenerator(inkex.Effect): CloseDebugFile() -if __name__ == '__main__': - BoxMakerGenericGenerator().run() \ No newline at end of file +# Create effect instance and apply it. +effect = GenericBox() +effect.run() diff --git a/extensions/fablabchemnitz/box_maker_generic_generator/inkscape_path.py b/extensions/fablabchemnitz/box_maker_generic_generator/th_inkscape_path.py similarity index 92% rename from extensions/fablabchemnitz/box_maker_generic_generator/inkscape_path.py rename to extensions/fablabchemnitz/box_maker_generic_generator/th_inkscape_path.py index 82023cf1..135ab586 100644 --- a/extensions/fablabchemnitz/box_maker_generic_generator/inkscape_path.py +++ b/extensions/fablabchemnitz/box_maker_generic_generator/th_inkscape_path.py @@ -2,6 +2,9 @@ # We will use the inkex module with the predefined Effect base class. import inkex +# The simplestyle module provides functions for style parsing. + +import simplestyle import math from lxml import etree @@ -28,12 +31,16 @@ class th_inkscape_path: self.ymax = -self.offsetY self.x = 0 self.y = 0 + self.x_noff = 0 + self.y_noff = 0 def MoveTo(self, x, y): #Return string 'M X Y' where X and Y are updated values from parameters self.Path += ' M ' + str(round(x-self.offsetX, 3)) + ',' + str(round(y-self.offsetY, 3)) self.x = x - self.offsetX self.y = y - self.offsetY + self.x_noff = x + self.y_noff = y self.xmin= min(self.x, self.xmin) self.xmax= max(self.x, self.xmax) self.ymin= min(self.y, self.ymin) @@ -44,6 +51,8 @@ class th_inkscape_path: self.Path += ' L ' + str(round(x-self.offsetX, 3)) + ',' + str(round(y-self.offsetY, 3)) self.x = x - self.offsetX self.y = y - self.offsetY + self.x_noff = x + self.y_noff = y self.xmin= min(self.x, self.xmin) self.xmax= max(self.x, self.xmax) self.ymin= min(self.y, self.ymin) @@ -55,6 +64,8 @@ class th_inkscape_path: self.Path += ' l ' + str(round(x, 3)) + ',' + str(round(y, 3)) self.x += x self.y += y + self.x_noff += x + self.y_noff += y self.xmin= min(self.x, self.xmin) self.xmax= max(self.x, self.xmax) self.ymin= min(self.y, self.ymin) @@ -64,6 +75,7 @@ class th_inkscape_path: #Return string 'h X' where X are updated values from parameters self.Path += ' h ' + str(round(x, 3)) self.x += x + self.x_noff += x self.xmin= min(self.x, self.xmin) self.xmax= max(self.x, self.xmax) @@ -72,6 +84,7 @@ class th_inkscape_path: #Return string 'v Y' where X and Y are updated values from parameters self.Path += ' v ' + str(round(y, 3)) self.y += y + self.y_noff += y self.ymin= min(self.y, self.ymin) self.ymax= max(self.y, self.ymax) @@ -86,6 +99,8 @@ class th_inkscape_path: self.Path += ' M ' + str(round(x1-self.offsetX, 3)) + ',' + str(round(y1-self.offsetY, 3)) + ' L ' + str(round(x2-self.offsetX, 3)) + ',' + str(round(y2-self.offsetY, 3)) self.x = x2 - self.offsetX self.y = y2 - self.offsetY + self.x_noff = x2 + self.y_noff = y2 self.xmin= min(self.x, self.xmin) self.xmax= max(self.x, self.xmax) self.ymin= min(self.y, self.ymin) @@ -94,6 +109,8 @@ class th_inkscape_path: def LineRel(self, x1, y1, x2, y2): self.x += x1 self.y += y1 + self.x_noff += x1 + self.y_noff += y1 self.xmin= min(self.x, self.xmin) self.xmax= max(self.x, self.xmax) self.ymin= min(self.y, self.ymin) @@ -103,6 +120,8 @@ class th_inkscape_path: self.Path += ' m ' + str(round(x1, 3)) + ',' + str(round(y1, 3)) + ' l ' + str(round(x2, 3)) + ',' + str(round(y2, 3)) self.x += x2 self.y += y2 + self.x_noff += x2 + self.y_noff += y2 self.xmin= min(self.x, self.xmin) self.xmax= max(self.x, self.xmax) self.ymin= min(self.y, self.ymin) @@ -113,6 +132,8 @@ class th_inkscape_path: self.Path += ' C ' + str(round(xc1-self.offsetX, 3)) + ',' + str(round(yc1-self.offsetY, 3)) + ' ' + str(round(xc2-self.offsetX, 3)) + ',' + str(round(yc2-self.offsetY, 3))+ ' ' + str(round(x-self.offsetX, 3)) + ',' + str(round(y-self.offsetY, 3)) self.x = x - self.offsetX self.y = y - self.offsetY + self.x_noff = x + self.y_noff = y self.xmin= min(self.x, self.xmin) self.xmax= max(self.x, self.xmax) self.ymin= min(self.y, self.ymin) @@ -123,6 +144,8 @@ class th_inkscape_path: self.Path += ' c ' + str(round(xc1, 3)) + ',' + str(round(yc1, 3)) + ' ' + str(round(xc2, 3)) + ',' + str(round(yc2, 3))+ ' ' + str(round(x, 3)) + ',' + str(round(y, 3)) self.x += x self.y += y + self.x_noff += x + self.y_noff += y self.xmin= min(self.x, self.xmin) self.xmax= max(self.x, self.xmax) self.ymin= min(self.y, self.ymin)