From baab1d87244ad0f89b3f0e1b71bc0d920ddb7fec Mon Sep 17 00:00:00 2001 From: alan Date: Sun, 16 Oct 2022 20:48:02 -0400 Subject: [PATCH 01/17] Add --insetkerf option to change direction of kerf compensation --- quickjoint.inx | 1 + quickjoint.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/quickjoint.inx b/quickjoint.inx index 42a585e..b761caa 100644 --- a/quickjoint.inx +++ b/quickjoint.inx @@ -28,6 +28,7 @@ False False + True path diff --git a/quickjoint.py b/quickjoint.py index 29c915b..f63f307 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -55,6 +55,7 @@ def add_arguments(self, pars): pars.add_argument('-e', '--edgefeatures', type=inkex.Boolean, default=False, help='Allow tabs to go right to edges') pars.add_argument('-f', '--flipside', type=inkex.Boolean, default=False, help='Flip side of lines that tabs are drawn onto') pars.add_argument('-a', '--activetab', default='', help='Tab or slot menus') + pars.add_argument('-i', '--insetkerf', type=inkex.Boolean, default=True, help='Kerf contracts tabs and slots instead of expanding them') def to_complex(self, command, line): debugMsg('To complex: ' + command + ' ' + str(line)) @@ -169,7 +170,7 @@ def draw_tabs(self, path, line): debugMsg('segLength - ' + str(segLength)) newLines = [] - # when handling firlt line need to set M back + # when handling first line need to set M back if isinstance(path[line], Move): newLines.append(['M', [start.real, start.imag]]) @@ -266,7 +267,12 @@ def effect(self): self.edgefeatures = self.options.edgefeatures self.flipside = self.options.flipside self.activetab = self.options.activetab - + self.insetkerf = self.options.insetkerf + + # Should kerf expand or contract slot size? inset = slot is contracted; kerf is subtracted from box + if self.insetkerf: + self.kerf = self.kerf * -1 + for id, node in self.svg.selected.items(): debugMsg(node) debugMsg('1') From a61caf913fb6debe1f31b9804407f0afa2902fc4 Mon Sep 17 00:00:00 2001 From: alan Date: Sun, 16 Oct 2022 21:11:25 -0400 Subject: [PATCH 02/17] refactor segLength calculation --- quickjoint.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/quickjoint.py b/quickjoint.py index f63f307..52d12a3 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -147,26 +147,23 @@ def draw_tabs(self, path, line): debugMsg('5-') - if self.edgefeatures: - segCount = (self.numtabs * 2) - 1 - drawValley = False - else: - segCount = (self.numtabs * 2) - drawValley = False - distance = end - start - debugMsg('distance ' + str(distance)) - debugMsg('segCount ' + str(segCount)) - + try: if self.edgefeatures: + segCount = (self.numtabs * 2) - 1 segLength = self.get_length(distance) / segCount else: + segCount = (self.numtabs * 2) segLength = self.get_length(distance) / (segCount + 1) except: - debugMsg('in except') + debugMsg('Exception calculating SegLength') segLength = self.get_length(distance) - + + drawValley = False + + debugMsg('distance ' + str(distance)) + debugMsg('segCount ' + str(segCount)) debugMsg('segLength - ' + str(segLength)) newLines = [] From 4b5e6d710d29f5c16199e902ccdef77e3da0c2db Mon Sep 17 00:00:00 2001 From: alan Date: Sun, 16 Oct 2022 22:18:27 -0400 Subject: [PATCH 03/17] Remove insetkerf, do the right thing automatically --- quickjoint.inx | 1 - 1 file changed, 1 deletion(-) diff --git a/quickjoint.inx b/quickjoint.inx index b761caa..42a585e 100644 --- a/quickjoint.inx +++ b/quickjoint.inx @@ -28,7 +28,6 @@ False False - True path From 78f8bd4cbc88a25096c66e7fba806c569f86c67b Mon Sep 17 00:00:00 2001 From: alan Date: Sun, 16 Oct 2022 22:29:10 -0400 Subject: [PATCH 04/17] Fix tabs with kerfs; only works without edgefeatures currently --- quickjoint.py | 124 +++++++++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 57 deletions(-) diff --git a/quickjoint.py b/quickjoint.py index 52d12a3..2085298 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -55,7 +55,6 @@ def add_arguments(self, pars): pars.add_argument('-e', '--edgefeatures', type=inkex.Boolean, default=False, help='Allow tabs to go right to edges') pars.add_argument('-f', '--flipside', type=inkex.Boolean, default=False, help='Flip side of lines that tabs are drawn onto') pars.add_argument('-a', '--activetab', default='', help='Tab or slot menus') - pars.add_argument('-i', '--insetkerf', type=inkex.Boolean, default=True, help='Kerf contracts tabs and slots instead of expanding them') def to_complex(self, command, line): debugMsg('To complex: ' + command + ' ' + str(line)) @@ -86,7 +85,11 @@ def draw_perpendicular(self, start, guideLine, stepDistance, invert = False): def draw_box(self, start, guideLine, xDistance, yDistance, kerf): polR, polPhi = cmath.polar(guideLine) - #Kerf expansion + # Kerf is a provided as a positive kerf width. Although tabs + # need to be made larger by the width of the kerf, slots need + # to be made narrower instead. + kerf = -kerf + if self.flipside: start -= cmath.rect(kerf / 2, polPhi) start -= cmath.rect(kerf / 2, polPhi + (cmath.pi / 2)) @@ -97,13 +100,13 @@ def draw_box(self, start, guideLine, xDistance, yDistance, kerf): lines = [] lines.append(['M', [start.real, start.imag]]) - #Horizontal + # Horizontal polR = xDistance move = cmath.rect(polR + kerf, polPhi) + start lines.append(['L', [move.real, move.imag]]) start = move - #Vertical + # Vertical polR = yDistance if self.flipside: polPhi += (cmath.pi / 2) @@ -113,7 +116,7 @@ def draw_box(self, start, guideLine, xDistance, yDistance, kerf): lines.append(['L', [move.real, move.imag]]) start = move - #Horizontal + # Horizontal polR = xDistance if self.flipside: polPhi += (cmath.pi / 2) @@ -126,9 +129,22 @@ def draw_box(self, start, guideLine, xDistance, yDistance, kerf): lines.append(['Z', []]) return lines - + + def vectorDraw(self, start, lines, vector): + start = start + vector + lines.append(['L', [start.real, start.imag]]) + return start + def draw_tabs(self, path, line): - #Male tab creation + + # Male tab creation is complicated by kerfs. + # I refer to this joint as a sequence of tabs and spaces with vertical runs between. + # Lengths of tabs and spaces must be adjusted by a portion of the kerf width. + # End tabs and spaces should be adjusted by half a kerf width, center tabs and spaces by a whole kerf width. + # Since we always have an odd number of segments, this balances the kerf adjustments. + + # Currently this code works withuot edgefeatures but is off by half a kerf width with edge features turned on. + start = to_complex(path[line]) closePath = False @@ -149,61 +165,60 @@ def draw_tabs(self, path, line): distance = end - start - try: - if self.edgefeatures: - segCount = (self.numtabs * 2) - 1 - segLength = self.get_length(distance) / segCount - else: - segCount = (self.numtabs * 2) - segLength = self.get_length(distance) / (segCount + 1) - except: - debugMsg('Exception calculating SegLength') - segLength = self.get_length(distance) + # Calculate the number of segments in the tabbed line: all tabs plus spaces. + if self.edgefeatures: + segCount = (self.numtabs * 2) - 1 + else: + segCount = (self.numtabs * 2) + 1 - drawValley = False - debugMsg('distance ' + str(distance)) debugMsg('segCount ' + str(segCount)) - debugMsg('segLength - ' + str(segLength)) + + # Calculate vectors for the parallel portion of tab, space, and endspace. + segment = distance / segCount + tabLine = self.draw_parallel(segment, segment, self.kerf) + spaceLine = self.draw_parallel(segment, segment, -self.kerf) + endspaceLine = self.draw_parallel(segment, segment, - self.kerf/2) + + # Calculate vectors for tabOut and tabIn: perpendicular away and towards baseline + tabOut = self.draw_perpendicular(0, distance, self.thickness, not self.flipside) + tabIn = self.draw_perpendicular(0, distance, self.thickness, self.flipside) + + # Count just the tabs and spaces without the end spaces (when not edgeFeature) + tabSpaceCount = self.numtabs * 2 - 1 + + # Distance doesn't need kerf adjustment: two parallel lines are the proper + # distance apart since they're both affected by the same kerf. + newLines = [] + cursor = start + debugMsg('Start: ' + str(start)) - # when handling first line need to set M back + # When handling first line, need to set M back if isinstance(path[line], Move): newLines.append(['M', [start.real, start.imag]]) - - if self.edgefeatures == False: - newLines.append(['L', [start.real, start.imag]]) - start = self.draw_parallel(start, distance, segLength) - newLines.append(['L', [start.real, start.imag]]) - debugMsg('Initial - ' + str(start)) - - for i in range(segCount): - if drawValley == True: - #Vertical - start = self.draw_perpendicular(start, distance, self.thickness, self.flipside) - newLines.append(['L', [start.real, start.imag]]) - debugMsg('ValleyV - ' + str(start)) - drawValley = False - #Horizontal - start = self.draw_parallel(start, distance, segLength) - newLines.append(['L', [start.real, start.imag]]) - debugMsg('ValleyH - ' + str(start)) + # If we aren't using edge features, add endspace + if self.edgefeatures == False: + cursor = self.vectorDraw(cursor, newLines, endspaceLine) + debugMsg('Cursor after endspace - ' + str(cursor)) + + # Starting on a tab, draw tabSpaceCount tabs and spaces. + drawTab = True; + for i in range(tabSpaceCount): + if drawTab == True: + cursor = self.vectorDraw(cursor, newLines, tabOut) + cursor = self.vectorDraw(cursor, newLines, tabLine) + cursor = self.vectorDraw(cursor, newLines, tabIn) else: - #Vertical - start = self.draw_perpendicular(start, distance, self.thickness, not self.flipside) - newLines.append(['L', [start.real, start.imag]]) - debugMsg('HillV - ' + str(start)) - drawValley = True - #Horizontal - start = self.draw_parallel(start, distance, segLength) - newLines.append(['L', [start.real, start.imag]]) - debugMsg('HillH - ' + str(start)) + cursor = self.vectorDraw(cursor, newLines, spaceLine) - if self.edgefeatures == True: - start = self.draw_perpendicular(start, distance, self.thickness, self.flipside) - newLines.append(['L', [start.real, start.imag]]) - debugMsg('Final - ' + str(start)) + drawTab = ~drawTab + + # If we aren't using edge features, add final endspace + if self.edgefeatures == False: + cursor = self.vectorDraw(cursor, newLines, endspaceLine) + debugMsg('Cursor after endspace - ' + str(cursor)) if closePath: newLines.append(['Z', []]) @@ -264,12 +279,7 @@ def effect(self): self.edgefeatures = self.options.edgefeatures self.flipside = self.options.flipside self.activetab = self.options.activetab - self.insetkerf = self.options.insetkerf - # Should kerf expand or contract slot size? inset = slot is contracted; kerf is subtracted from box - if self.insetkerf: - self.kerf = self.kerf * -1 - for id, node in self.svg.selected.items(): debugMsg(node) debugMsg('1') From 1ace435d06d32ce210e39c6adc7f2b1bdc6bee5d Mon Sep 17 00:00:00 2001 From: alan Date: Sun, 16 Oct 2022 22:57:03 -0400 Subject: [PATCH 05/17] Make tab kerf code work with edge features --- quickjoint.py | 78 ++++++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 45 deletions(-) diff --git a/quickjoint.py b/quickjoint.py index 2085298..74906f6 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -26,7 +26,7 @@ from inkex.paths import Path, ZoneClose, Move from lxml import etree -debugEn = False +debugEn = False def debugMsg(input): if debugEn: inkex.utils.debug(input) @@ -87,7 +87,7 @@ def draw_box(self, start, guideLine, xDistance, yDistance, kerf): # Kerf is a provided as a positive kerf width. Although tabs # need to be made larger by the width of the kerf, slots need - # to be made narrower instead. + # to be made narrower instead, since the kerf widens them. kerf = -kerf if self.flipside: @@ -136,15 +136,12 @@ def vectorDraw(self, start, lines, vector): return start def draw_tabs(self, path, line): - # Male tab creation is complicated by kerfs. - # I refer to this joint as a sequence of tabs and spaces with vertical runs between. - # Lengths of tabs and spaces must be adjusted by a portion of the kerf width. + # For the tab creation code: the joint is a sequence of tabs and spaces with perpendicular shifts between them. + # The lengths of tabs and spaces must be adjusted by a portion of the kerf width, but the depth does not. + # Tabs should be longer and spaces should be shorter, since the kerf reduces the width of each tab. # End tabs and spaces should be adjusted by half a kerf width, center tabs and spaces by a whole kerf width. # Since we always have an odd number of segments, this balances the kerf adjustments. - - # Currently this code works withuot edgefeatures but is off by half a kerf width with edge features turned on. - start = to_complex(path[line]) closePath = False @@ -156,12 +153,7 @@ def draw_tabs(self, path, line): else: end = to_complex(path[line+1]) - debugMsg('start') - debugMsg(start) - debugMsg('end') - debugMsg(end) - - debugMsg('5-') + debugMsg('start: ' + str(start) + "; snd: " + str(end)) distance = end - start @@ -171,12 +163,13 @@ def draw_tabs(self, path, line): else: segCount = (self.numtabs * 2) + 1 - debugMsg('distance ' + str(distance)) - debugMsg('segCount ' + str(segCount)) + debugMsg('distance: ' + str(distance)) + debugMsg('segCount: ' + str(segCount)) # Calculate vectors for the parallel portion of tab, space, and endspace. segment = distance / segCount tabLine = self.draw_parallel(segment, segment, self.kerf) + endtabLine = self.draw_parallel(segment, segment, self.kerf/2) spaceLine = self.draw_parallel(segment, segment, -self.kerf) endspaceLine = self.draw_parallel(segment, segment, - self.kerf/2) @@ -184,42 +177,37 @@ def draw_tabs(self, path, line): tabOut = self.draw_perpendicular(0, distance, self.thickness, not self.flipside) tabIn = self.draw_perpendicular(0, distance, self.thickness, self.flipside) - # Count just the tabs and spaces without the end spaces (when not edgeFeature) - tabSpaceCount = self.numtabs * 2 - 1 - - # Distance doesn't need kerf adjustment: two parallel lines are the proper - # distance apart since they're both affected by the same kerf. - newLines = [] - cursor = start - debugMsg('Start: ' + str(start)) - # When handling first line, need to set M back if isinstance(path[line], Move): newLines.append(['M', [start.real, start.imag]]) - - # If we aren't using edge features, add endspace - if self.edgefeatures == False: - cursor = self.vectorDraw(cursor, newLines, endspaceLine) - debugMsg('Cursor after endspace - ' + str(cursor)) - # Starting on a tab, draw tabSpaceCount tabs and spaces. - drawTab = True; - for i in range(tabSpaceCount): - if drawTab == True: - cursor = self.vectorDraw(cursor, newLines, tabOut) - cursor = self.vectorDraw(cursor, newLines, tabLine) - cursor = self.vectorDraw(cursor, newLines, tabIn) + drawTab = self.edgefeatures + newLines = [] + cursor = start + + for i in range(segCount): + debugMsg("i = " + str(i)) + if i == 0 or i == segCount - 1: + if drawTab == True: + debugMsg("- end tab") + cursor = self.vectorDraw(cursor, newLines, tabOut) + cursor = self.vectorDraw(cursor, newLines, endtabLine) + cursor = self.vectorDraw(cursor, newLines, tabIn) + else: + debugMsg("- end space") + cursor = self.vectorDraw(cursor, newLines, endspaceLine) else: - cursor = self.vectorDraw(cursor, newLines, spaceLine) - - drawTab = ~drawTab + if drawTab == True: + debugMsg("- tab") + cursor = self.vectorDraw(cursor, newLines, tabOut) + cursor = self.vectorDraw(cursor, newLines, tabLine) + cursor = self.vectorDraw(cursor, newLines, tabIn) + else: + debugMsg("- space") + cursor = self.vectorDraw(cursor, newLines, spaceLine) + drawTab = not drawTab - # If we aren't using edge features, add final endspace - if self.edgefeatures == False: - cursor = self.vectorDraw(cursor, newLines, endspaceLine) - debugMsg('Cursor after endspace - ' + str(cursor)) - if closePath: newLines.append(['Z', []]) return newLines From 483c4fe7c8f85db1828da4ff5efa628b68c1c723 Mon Sep 17 00:00:00 2001 From: alan Date: Sun, 16 Oct 2022 23:13:44 -0400 Subject: [PATCH 06/17] Typo --- quickjoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickjoint.py b/quickjoint.py index 74906f6..ac65d85 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -153,7 +153,7 @@ def draw_tabs(self, path, line): else: end = to_complex(path[line+1]) - debugMsg('start: ' + str(start) + "; snd: " + str(end)) + debugMsg('start: ' + str(start) + "; end: " + str(end)) distance = end - start From 05bb0b0510c076d10c916ce77ce22952e550191d Mon Sep 17 00:00:00 2001 From: alan Date: Tue, 18 Oct 2022 19:43:49 -0400 Subject: [PATCH 07/17] Add support for selecting features on each end separately --- quickjoint.inx | 3 +- quickjoint.py | 85 +++++++++++++++++++++++--------------------------- 2 files changed, 41 insertions(+), 47 deletions(-) diff --git a/quickjoint.inx b/quickjoint.inx index 42a585e..300631d 100644 --- a/quickjoint.inx +++ b/quickjoint.inx @@ -26,7 +26,8 @@ in cm - False + False + False False path diff --git a/quickjoint.py b/quickjoint.py index ac65d85..d077fd1 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -26,7 +26,7 @@ from inkex.paths import Path, ZoneClose, Move from lxml import etree -debugEn = False +debugEn = True def debugMsg(input): if debugEn: inkex.utils.debug(input) @@ -52,9 +52,10 @@ def add_arguments(self, pars): pars.add_argument('-t', '--thickness', type=float, default=3.0, help='Material thickness') pars.add_argument('-k', '--kerf', type=float, default=0.14, help='Measured kerf of cutter') pars.add_argument('-u', '--units', default='mm', help='Measurement units') - pars.add_argument('-e', '--edgefeatures', type=inkex.Boolean, default=False, help='Allow tabs to go right to edges') pars.add_argument('-f', '--flipside', type=inkex.Boolean, default=False, help='Flip side of lines that tabs are drawn onto') pars.add_argument('-a', '--activetab', default='', help='Tab or slot menus') + pars.add_argument('-S', '--featureStart', type=inkex.Boolean, default=False, help='Tab/slot instead of space on the start edge') + pars.add_argument('-E', '--featureEnd', type=inkex.Boolean, default=False, help='Tab/slot instead of space on the end edge') def to_complex(self, command, line): debugMsg('To complex: ' + command + ' ' + str(line)) @@ -158,11 +159,10 @@ def draw_tabs(self, path, line): distance = end - start # Calculate the number of segments in the tabbed line: all tabs plus spaces. - if self.edgefeatures: - segCount = (self.numtabs * 2) - 1 - else: - segCount = (self.numtabs * 2) + 1 - + segCount = self.numtabs * 2 - 1 + if not self.featureStart: segCount = segCount + 1 + if not self.featureEnd: segCount = segCount + 1 + debugMsg('distance: ' + str(distance)) debugMsg('segCount: ' + str(segCount)) @@ -177,15 +177,16 @@ def draw_tabs(self, path, line): tabOut = self.draw_perpendicular(0, distance, self.thickness, not self.flipside) tabIn = self.draw_perpendicular(0, distance, self.thickness, self.flipside) + drawTab = self.featureStart + newLines = [] + cursor = start # When handling first line, need to set M back if isinstance(path[line], Move): newLines.append(['M', [start.real, start.imag]]) - - drawTab = self.edgefeatures - newLines = [] - cursor = start - + else: + newLines.append(['L', [start.real, start.imag]]) + for i in range(segCount): debugMsg("i = " + str(i)) if i == 0 or i == segCount - 1: @@ -212,50 +213,41 @@ def draw_tabs(self, path, line): newLines.append(['Z', []]) return newLines - - def draw_slots(self, path): - #Female slot creation + def add_new_path_from_lines(self, lines, line_style): + slot_id = self.svg.get_unique_id('slot') + g = etree.SubElement(self.svg.get_current_layer(), 'g', {'id':slot_id}) + line_atts = { 'style':line_style, 'id':slot_id+'-inner-close-tab', 'd':str(Path(lines)) } + etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) + + def draw_slots(self, path): + # Female slot creation start = to_complex(path[0]) end = to_complex(path[1]) - if self.edgefeatures: - segCount = (self.numslots * 2) - 1 - else: - segCount = (self.numslots * 2) - + # Total number of segments including all slots and spaces + segCount = self.numslots * 2 - 1 + if not self.featureStart: segCount = segCount + 1 + if not self.featureEnd: segCount = segCount + 1 + distance = end - start debugMsg('distance ' + str(distance)) debugMsg('segCount ' + str(segCount)) - - try: - if self.edgefeatures: - segLength = self.get_length(distance) / segCount - else: - segLength = self.get_length(distance) / (segCount + 1) - except: - segLength = self.get_length(distance) - + + segLength = self.get_length(distance) / segCount debugMsg('segLength - ' + str(segLength)) + + segVector = distance / segCount newLines = [] - line_style = str(inkex.Style({ 'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.svg.unittouu('0.1mm')) })) - + drawSlot = self.featureStart + cursor = start for i in range(segCount): - if (self.edgefeatures and (i % 2) == 0) or (not self.edgefeatures and (i % 2)): - newLines = self.draw_box(start, distance, segLength, self.thickness, self.kerf) - debugMsg(newLines) - - slot_id = self.svg.get_unique_id('slot') - g = etree.SubElement(self.svg.get_current_layer(), 'g', {'id':slot_id}) - - line_atts = { 'style':line_style, 'id':slot_id+'-inner-close-tab', 'd':str(Path(newLines)) } - etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) - - #Find next point - polR, polPhi = cmath.polar(distance) - polR = segLength - start = cmath.rect(polR, polPhi) + start + if drawSlot: + self.add_new_path_from_lines(self.draw_box(cursor, distance, segLength, self.thickness, self.kerf), line_style) + cursor = cursor + segVector + drawSlot = not drawSlot + debugMsg("i: " + str(i) + ", cursor: " + str(cursor)) def effect(self): self.side = self.options.side @@ -264,7 +256,8 @@ def effect(self): self.thickness = self.svg.unittouu(str(self.options.thickness) + self.options.units) self.kerf = self.svg.unittouu(str(self.options.kerf) + self.options.units) self.units = self.options.units - self.edgefeatures = self.options.edgefeatures + self.featureStart = self.options.featureStart + self.featureEnd = self.options.featureEnd self.flipside = self.options.flipside self.activetab = self.options.activetab From e4577516a2cd0ee46bfbe06639a8979a7766676a Mon Sep 17 00:00:00 2001 From: alan Date: Tue, 18 Oct 2022 20:25:58 -0400 Subject: [PATCH 08/17] Turn off debugging --- quickjoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickjoint.py b/quickjoint.py index d077fd1..5d8e52a 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -26,7 +26,7 @@ from inkex.paths import Path, ZoneClose, Move from lxml import etree -debugEn = True +debugEn = False def debugMsg(input): if debugEn: inkex.utils.debug(input) From 059dd14aef595d8edae066988e8a274877e488f4 Mon Sep 17 00:00:00 2001 From: alan Date: Wed, 19 Oct 2022 22:54:21 -0400 Subject: [PATCH 09/17] Refactor draw_box to accept a vector to avoid need for segment length scalar --- quickjoint.py | 72 ++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/quickjoint.py b/quickjoint.py index 5d8e52a..fed9476 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -82,50 +82,49 @@ def draw_perpendicular(self, start, guideLine, stepDistance, invert = False): debugMsg(polPhi) debugMsg(cmath.rect(polR, polPhi)) return (cmath.rect(polR, polPhi) + start) + + def move(self, lines, point): + debugMsg("- move: " + str(point)) + lines.append(['M', [point.real, point.imag]]) - def draw_box(self, start, guideLine, xDistance, yDistance, kerf): - polR, polPhi = cmath.polar(guideLine) + def line(self, lines, point): + debugMsg("- line: " + str(point)) + lines.append(['L', [point.real, point.imag]]) + def draw_box(self, start, lengthVector, height, kerf): + length, lengthDirection = cmath.polar(lengthVector) + heightDirection = lengthDirection - (cmath.pi / 2) + if self.flipside: heightDirection = -heightDirection + + debugMsg("draw_box; lengthVector: " + str(lengthVector) + ", kerf: " + str(kerf)) + + cursor = start # Kerf is a provided as a positive kerf width. Although tabs # need to be made larger by the width of the kerf, slots need # to be made narrower instead, since the kerf widens them. kerf = -kerf - - if self.flipside: - start -= cmath.rect(kerf / 2, polPhi) - start -= cmath.rect(kerf / 2, polPhi + (cmath.pi / 2)) - else: - start -= cmath.rect(kerf / 2, polPhi) - start -= cmath.rect(kerf / 2, polPhi - (cmath.pi / 2)) - + + cursor -= cmath.rect(kerf/2, lengthDirection) + cursor -= cmath.rect(kerf/2, heightDirection) + lines = [] - lines.append(['M', [start.real, start.imag]]) + self.move(lines, cursor) - # Horizontal - polR = xDistance - move = cmath.rect(polR + kerf, polPhi) + start - lines.append(['L', [move.real, move.imag]]) - start = move + # Slot length + cursor += cmath.rect(length + kerf, lengthDirection) + self.line(lines, cursor) - # Vertical - polR = yDistance - if self.flipside: - polPhi += (cmath.pi / 2) - else: - polPhi -= (cmath.pi / 2) - move = cmath.rect(polR + kerf, polPhi) + start - lines.append(['L', [move.real, move.imag]]) - start = move + # Slot height + cursor += cmath.rect(height + kerf, heightDirection) + self.line(lines, cursor) - # Horizontal - polR = xDistance - if self.flipside: - polPhi += (cmath.pi / 2) - else: - polPhi -= (cmath.pi / 2) - move = cmath.rect(polR + kerf, polPhi) + start - lines.append(['L', [move.real, move.imag]]) - start = move + # Back slot length + cursor += cmath.rect(length + kerf, lengthDirection + cmath.pi) + self.line(lines, cursor) + + # Back Slot height + cursor += cmath.rect(height + kerf, heightDirection + cmath.pi) + self.line(lines, cursor) lines.append(['Z', []]) @@ -234,9 +233,6 @@ def draw_slots(self, path): debugMsg('distance ' + str(distance)) debugMsg('segCount ' + str(segCount)) - segLength = self.get_length(distance) / segCount - debugMsg('segLength - ' + str(segLength)) - segVector = distance / segCount newLines = [] line_style = str(inkex.Style({ 'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.svg.unittouu('0.1mm')) })) @@ -244,7 +240,7 @@ def draw_slots(self, path): cursor = start for i in range(segCount): if drawSlot: - self.add_new_path_from_lines(self.draw_box(cursor, distance, segLength, self.thickness, self.kerf), line_style) + self.add_new_path_from_lines(self.draw_box(cursor, segVector, self.thickness, self.kerf), line_style) cursor = cursor + segVector drawSlot = not drawSlot debugMsg("i: " + str(i) + ", cursor: " + str(cursor)) From 03771a3c1c66aaa3ba57d181a158de0f8e954e98 Mon Sep 17 00:00:00 2001 From: alan Date: Wed, 19 Oct 2022 22:55:34 -0400 Subject: [PATCH 10/17] Remove unused get_length --- quickjoint.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/quickjoint.py b/quickjoint.py index fed9476..9a3450e 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -62,10 +62,6 @@ def to_complex(self, command, line): return complex(line[0], line[1]) - def get_length(self, line): - polR, polPhi = cmath.polar(line) - return polR - def draw_parallel(self, start, guideLine, stepDistance): polR, polPhi = cmath.polar(guideLine) polR = stepDistance From dba2a4941305342240a12ad284a996fbc7f1cbf2 Mon Sep 17 00:00:00 2001 From: alan Date: Wed, 19 Oct 2022 23:08:26 -0400 Subject: [PATCH 11/17] rewrite draw_box to use vectors --- quickjoint.py | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/quickjoint.py b/quickjoint.py index 9a3450e..76a217a 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -88,38 +88,33 @@ def line(self, lines, point): lines.append(['L', [point.real, point.imag]]) def draw_box(self, start, lengthVector, height, kerf): - length, lengthDirection = cmath.polar(lengthVector) - heightDirection = lengthDirection - (cmath.pi / 2) - if self.flipside: heightDirection = -heightDirection - debugMsg("draw_box; lengthVector: " + str(lengthVector) + ", kerf: " + str(kerf)) - - cursor = start # Kerf is a provided as a positive kerf width. Although tabs # need to be made larger by the width of the kerf, slots need - # to be made narrower instead, since the kerf widens them. - kerf = -kerf + # to be made narrower instead, since the cut widens them. + + # Calculate kerfed height and length vectors + heightEdge = self.draw_perpendicular(0, lengthVector, height - kerf, self.flipside) + lengthEdge = self.draw_parallel(lengthVector, lengthVector, -kerf) + + debugMsg("draw_box; lengthEdge: " + str(lengthEdge) + ", heightEdge: " + str(heightEdge)) - cursor -= cmath.rect(kerf/2, lengthDirection) - cursor -= cmath.rect(kerf/2, heightDirection) + cursor = self.draw_parallel(start, lengthEdge, kerf/2) + cursor = self.draw_perpendicular(cursor, heightEdge, kerf/2) lines = [] self.move(lines, cursor) - # Slot length - cursor += cmath.rect(length + kerf, lengthDirection) + cursor += lengthEdge self.line(lines, cursor) - # Slot height - cursor += cmath.rect(height + kerf, heightDirection) + cursor += heightEdge self.line(lines, cursor) - # Back slot length - cursor += cmath.rect(length + kerf, lengthDirection + cmath.pi) + cursor -= lengthEdge self.line(lines, cursor) - # Back Slot height - cursor += cmath.rect(height + kerf, heightDirection + cmath.pi) + cursor -= heightEdge self.line(lines, cursor) lines.append(['Z', []]) @@ -128,7 +123,7 @@ def draw_box(self, start, lengthVector, height, kerf): def vectorDraw(self, start, lines, vector): start = start + vector - lines.append(['L', [start.real, start.imag]]) + self.draw(lines, start) return start def draw_tabs(self, path, line): From 717da7d94f1eefa090177fccfcfc80cc252d8d5a Mon Sep 17 00:00:00 2001 From: alan Date: Wed, 19 Oct 2022 23:22:27 -0400 Subject: [PATCH 12/17] Factor out get_segments so I only have to patch it once --- quickjoint.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/quickjoint.py b/quickjoint.py index 76a217a..450d811 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -100,7 +100,7 @@ def draw_box(self, start, lengthVector, height, kerf): debugMsg("draw_box; lengthEdge: " + str(lengthEdge) + ", heightEdge: " + str(heightEdge)) cursor = self.draw_parallel(start, lengthEdge, kerf/2) - cursor = self.draw_perpendicular(cursor, heightEdge, kerf/2) + cursor = self.draw_parallel(cursor, heightEdge, kerf/2) lines = [] self.move(lines, cursor) @@ -123,7 +123,7 @@ def draw_box(self, start, lengthVector, height, kerf): def vectorDraw(self, start, lines, vector): start = start + vector - self.draw(lines, start) + self.line(lines, start) return start def draw_tabs(self, path, line): @@ -210,25 +210,31 @@ def add_new_path_from_lines(self, lines, line_style): line_atts = { 'style':line_style, 'id':slot_id+'-inner-close-tab', 'd':str(Path(lines)) } etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) - def draw_slots(self, path): - # Female slot creation + def get_segments(self, path): start = to_complex(path[0]) end = to_complex(path[1]) + edge = end - start + # Total number of segments including all slots and spaces segCount = self.numslots * 2 - 1 if not self.featureStart: segCount = segCount + 1 if not self.featureEnd: segCount = segCount + 1 + segVector = edge / segCount + + debugMsg("get_segments; start=" + str(start) + " segCount=" + str(segCount) + " segVector=" + str(segVector)) - distance = end - start - debugMsg('distance ' + str(distance)) - debugMsg('segCount ' + str(segCount)) + return (start, segCount, segVector) + + def draw_slots(self, path): + # Female slot creation + + cursor, segCount, segVector = self.get_segments(path) - segVector = distance / segCount newLines = [] line_style = str(inkex.Style({ 'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.svg.unittouu('0.1mm')) })) drawSlot = self.featureStart - cursor = start + for i in range(segCount): if drawSlot: self.add_new_path_from_lines(self.draw_box(cursor, segVector, self.thickness, self.kerf), line_style) From a224084e20a35cfaa9edbfe9aece13bca00083d8 Mon Sep 17 00:00:00 2001 From: alan Date: Wed, 19 Oct 2022 23:38:14 -0400 Subject: [PATCH 13/17] Use get_segments in draw_tabs --- quickjoint.py | 54 +++++++++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 34 deletions(-) diff --git a/quickjoint.py b/quickjoint.py index 450d811..cf629ad 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -133,49 +133,26 @@ def draw_tabs(self, path, line): # Tabs should be longer and spaces should be shorter, since the kerf reduces the width of each tab. # End tabs and spaces should be adjusted by half a kerf width, center tabs and spaces by a whole kerf width. # Since we always have an odd number of segments, this balances the kerf adjustments. - start = to_complex(path[line]) - - closePath = False - #Line is between last and first (closed) nodes - end = None - if isinstance(path[line+1], ZoneClose): - end = to_complex(path[0]) - closePath = True - else: - end = to_complex(path[line+1]) - - debugMsg('start: ' + str(start) + "; end: " + str(end)) - - distance = end - start - - # Calculate the number of segments in the tabbed line: all tabs plus spaces. - segCount = self.numtabs * 2 - 1 - if not self.featureStart: segCount = segCount + 1 - if not self.featureEnd: segCount = segCount + 1 + cursor, segCount, segment, closePath = self.get_segments(path, line) - debugMsg('distance: ' + str(distance)) - debugMsg('segCount: ' + str(segCount)) - # Calculate vectors for the parallel portion of tab, space, and endspace. - segment = distance / segCount tabLine = self.draw_parallel(segment, segment, self.kerf) endtabLine = self.draw_parallel(segment, segment, self.kerf/2) spaceLine = self.draw_parallel(segment, segment, -self.kerf) endspaceLine = self.draw_parallel(segment, segment, - self.kerf/2) # Calculate vectors for tabOut and tabIn: perpendicular away and towards baseline - tabOut = self.draw_perpendicular(0, distance, self.thickness, not self.flipside) - tabIn = self.draw_perpendicular(0, distance, self.thickness, self.flipside) + tabOut = self.draw_perpendicular(0, segment, self.thickness, not self.flipside) + tabIn = self.draw_perpendicular(0, segment, self.thickness, self.flipside) drawTab = self.featureStart newLines = [] - cursor = start # When handling first line, need to set M back if isinstance(path[line], Move): - newLines.append(['M', [start.real, start.imag]]) + self.move(newLines, cursor) else: - newLines.append(['L', [start.real, start.imag]]) + self.line(newLines, cursor) for i in range(segCount): debugMsg("i = " + str(i)) @@ -210,9 +187,17 @@ def add_new_path_from_lines(self, lines, line_style): line_atts = { 'style':line_style, 'id':slot_id+'-inner-close-tab', 'd':str(Path(lines)) } etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) - def get_segments(self, path): - start = to_complex(path[0]) - end = to_complex(path[1]) + def get_segments(self, path, line): + start = to_complex(path[line]) + + # Calculate end. If the next point in the path closes the path, go back to the start. + end = None + closePath = False + if isinstance(path[line+1], ZoneClose): + end = to_complex(path[0]) + closePath = True + else: + end = to_complex(path[line+1]) edge = end - start @@ -224,12 +209,12 @@ def get_segments(self, path): debugMsg("get_segments; start=" + str(start) + " segCount=" + str(segCount) + " segVector=" + str(segVector)) - return (start, segCount, segVector) + return (start, segCount, segVector, closePath) def draw_slots(self, path): # Female slot creation - cursor, segCount, segVector = self.get_segments(path) + cursor, segCount, segVector, closePath = self.get_segments(path, 0) newLines = [] line_style = str(inkex.Style({ 'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.svg.unittouu('0.1mm')) })) @@ -241,7 +226,8 @@ def draw_slots(self, path): cursor = cursor + segVector drawSlot = not drawSlot debugMsg("i: " + str(i) + ", cursor: " + str(cursor)) - + # (We don't modify the path so we don't need to close it) + def effect(self): self.side = self.options.side self.numtabs = self.options.numtabs From 40a6a5f62b365e8af6d25f8d28651553fb58e954 Mon Sep 17 00:00:00 2001 From: alan Date: Thu, 20 Oct 2022 00:23:11 -0400 Subject: [PATCH 14/17] Fix width of end tabs and slots Slightly complicated, but: the line segment we're provided isn't the length of material that will be left after it's cut, because of the kerf. We need to divide the shorter length into equal portions, and then let draw_tab add the kerf back on. --- quickjoint.py | 64 +++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/quickjoint.py b/quickjoint.py index cf629ad..f1ec30a 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -127,19 +127,11 @@ def vectorDraw(self, start, lines, vector): return start def draw_tabs(self, path, line): - # Male tab creation is complicated by kerfs. - # For the tab creation code: the joint is a sequence of tabs and spaces with perpendicular shifts between them. - # The lengths of tabs and spaces must be adjusted by a portion of the kerf width, but the depth does not. - # Tabs should be longer and spaces should be shorter, since the kerf reduces the width of each tab. - # End tabs and spaces should be adjusted by half a kerf width, center tabs and spaces by a whole kerf width. - # Since we always have an odd number of segments, this balances the kerf adjustments. cursor, segCount, segment, closePath = self.get_segments(path, line) - # Calculate vectors for the parallel portion of tab, space, and endspace. + # Calculate kerf-compensated vectors for the parallel portion of tab and space tabLine = self.draw_parallel(segment, segment, self.kerf) - endtabLine = self.draw_parallel(segment, segment, self.kerf/2) spaceLine = self.draw_parallel(segment, segment, -self.kerf) - endspaceLine = self.draw_parallel(segment, segment, - self.kerf/2) # Calculate vectors for tabOut and tabIn: perpendicular away and towards baseline tabOut = self.draw_perpendicular(0, segment, self.thickness, not self.flipside) @@ -156,24 +148,14 @@ def draw_tabs(self, path, line): for i in range(segCount): debugMsg("i = " + str(i)) - if i == 0 or i == segCount - 1: - if drawTab == True: - debugMsg("- end tab") - cursor = self.vectorDraw(cursor, newLines, tabOut) - cursor = self.vectorDraw(cursor, newLines, endtabLine) - cursor = self.vectorDraw(cursor, newLines, tabIn) - else: - debugMsg("- end space") - cursor = self.vectorDraw(cursor, newLines, endspaceLine) + if drawTab == True: + debugMsg("- tab") + cursor = self.vectorDraw(cursor, newLines, tabOut) + cursor = self.vectorDraw(cursor, newLines, tabLine) + cursor = self.vectorDraw(cursor, newLines, tabIn) else: - if drawTab == True: - debugMsg("- tab") - cursor = self.vectorDraw(cursor, newLines, tabOut) - cursor = self.vectorDraw(cursor, newLines, tabLine) - cursor = self.vectorDraw(cursor, newLines, tabIn) - else: - debugMsg("- space") - cursor = self.vectorDraw(cursor, newLines, spaceLine) + debugMsg("- space") + cursor = self.vectorDraw(cursor, newLines, spaceLine) drawTab = not drawTab if closePath: @@ -188,9 +170,15 @@ def add_new_path_from_lines(self, lines, line_style): etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) def get_segments(self, path, line): - start = to_complex(path[line]) - # Calculate end. If the next point in the path closes the path, go back to the start. + # Calculate number of segments, including all features and spaces + segCount = self.numslots * 2 - 1 + if not self.featureStart: segCount = segCount + 1 + if not self.featureEnd: segCount = segCount + 1 + + # Calculate the start and end of the edge we've been told to modify. + start = to_complex(path[line]) + # If the next point in the path closes the path, go back to the start. end = None closePath = False if isinstance(path[line+1], ZoneClose): @@ -199,15 +187,17 @@ def get_segments(self, path, line): else: end = to_complex(path[line+1]) - edge = end - start + # Calculate the length of each feature prior to kerf compensation. + # Here we divide the specified edge into equal portions, one for each feature or space. - # Total number of segments including all slots and spaces - segCount = self.numslots * 2 - 1 - if not self.featureStart: segCount = segCount + 1 - if not self.featureEnd: segCount = segCount + 1 + # Because the specified edge has no kerf compensation, the + # actual length we end up with will be smaller by a kerf. We + # need to use that distance to calculate our segment vector. + edge = end - start + edge = self.draw_parallel(edge, edge, -self.kerf) segVector = edge / segCount - - debugMsg("get_segments; start=" + str(start) + " segCount=" + str(segCount) + " segVector=" + str(segVector)) + + debugMsg("get_segments; start=" + str(start) + " end=" + str(end) + " edge=" + str(edge) + " segCount=" + str(segCount) + " segVector=" + str(segVector)) return (start, segCount, segVector, closePath) @@ -216,6 +206,10 @@ def draw_slots(self, path): cursor, segCount, segVector, closePath = self.get_segments(path, 0) + # I'm having a really hard time wording why this is necessary, but it is. + # get_segments returns a vector based on a narrower edge; adjust that edge to fit within the edge we were given. + cursor = self.draw_parallel(cursor, segVector, self.kerf/2) + newLines = [] line_style = str(inkex.Style({ 'stroke': '#000000', 'fill': 'none', 'stroke-width': str(self.svg.unittouu('0.1mm')) })) drawSlot = self.featureStart From bb13039e58fe180ce95841f7ad78b3b85df62614 Mon Sep 17 00:00:00 2001 From: alan Date: Thu, 20 Oct 2022 01:10:30 -0400 Subject: [PATCH 15/17] Fix bug with numtabs/numslots; bring back endspace to fix tabs not on end --- quickjoint.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/quickjoint.py b/quickjoint.py index f1ec30a..c5db972 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -127,16 +127,19 @@ def vectorDraw(self, start, lines, vector): return start def draw_tabs(self, path, line): - cursor, segCount, segment, closePath = self.get_segments(path, line) + cursor, segCount, segment, closePath = self.get_segments(path, line, self.numtabs) # Calculate kerf-compensated vectors for the parallel portion of tab and space tabLine = self.draw_parallel(segment, segment, self.kerf) spaceLine = self.draw_parallel(segment, segment, -self.kerf) + endspaceLine = segment # Calculate vectors for tabOut and tabIn: perpendicular away and towards baseline tabOut = self.draw_perpendicular(0, segment, self.thickness, not self.flipside) tabIn = self.draw_perpendicular(0, segment, self.thickness, self.flipside) + debugMsg("draw_tabs; tabLine=" + str(tabLine) + " spaceLine=" + str(spaceLine) + " segment=" + str(segment)) + drawTab = self.featureStart newLines = [] @@ -154,8 +157,12 @@ def draw_tabs(self, path, line): cursor = self.vectorDraw(cursor, newLines, tabLine) cursor = self.vectorDraw(cursor, newLines, tabIn) else: - debugMsg("- space") - cursor = self.vectorDraw(cursor, newLines, spaceLine) + if i == 0 or i == segCount - 1: + debugMsg("- endspace") + cursor = self.vectorDraw(cursor, newLines, endspaceLine) + else: + debugMsg("- space") + cursor = self.vectorDraw(cursor, newLines, spaceLine) drawTab = not drawTab if closePath: @@ -169,10 +176,10 @@ def add_new_path_from_lines(self, lines, line_style): line_atts = { 'style':line_style, 'id':slot_id+'-inner-close-tab', 'd':str(Path(lines)) } etree.SubElement(g, inkex.addNS('path','svg'), line_atts ) - def get_segments(self, path, line): + def get_segments(self, path, line, num): # Calculate number of segments, including all features and spaces - segCount = self.numslots * 2 - 1 + segCount = num * 2 - 1 if not self.featureStart: segCount = segCount + 1 if not self.featureEnd: segCount = segCount + 1 @@ -204,7 +211,7 @@ def get_segments(self, path, line): def draw_slots(self, path): # Female slot creation - cursor, segCount, segVector, closePath = self.get_segments(path, 0) + cursor, segCount, segVector, closePath = self.get_segments(path, 0, self.numslots) # I'm having a really hard time wording why this is necessary, but it is. # get_segments returns a vector based on a narrower edge; adjust that edge to fit within the edge we were given. From 639cd99e3a6c87b01e84333834bc98d9db08db28 Mon Sep 17 00:00:00 2001 From: alan Date: Thu, 20 Oct 2022 14:10:40 -0400 Subject: [PATCH 16/17] Factor out path module and use inkex.path commands --- quickjoint.py | 104 ++++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 49 deletions(-) diff --git a/quickjoint.py b/quickjoint.py index c5db972..130d0d5 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -23,7 +23,7 @@ ''' import inkex, cmath -from inkex.paths import Path, ZoneClose, Move +from inkex.paths import Path, ZoneClose, Move, Line, line from lxml import etree debugEn = False @@ -40,9 +40,37 @@ def linesNumber(path): debugMsg('Number of lines : ' + str(retval)) return retval -def to_complex(point): - return complex(point.x, point.y) - +class QuickJointPath (Path): + def Move(self, point): + '''Append an absolute move instruction to the path, to the specified complex point''' + debugMsg("- move: " + str(point)) + self.append(Move(point.real, point.imag)) + + def Line(self, point): + '''Add an absolute line instruction to the path, to the specified complex point''' + debugMsg("- line: " + str(point)) + self.append(Line(point.real, point.imag)) + + def close(self): + '''Add a Close Path instriction to the path''' + self.append(ZoneClose()) + + def line(self, vector): + '''Append a relative line command to the path, using the specified vector''' + self.append(line(vector.real, vector.imag)) + + def get_line(self, n): + '''Return the end points of the nth line in the path as complex numbers, as well as whether that line closes the path.''' + start = complex(self[n].real, self[n].imag) + # If the next point in the path closes the path, go back to the start. + end = None + closePath = False + if isinstance(self[n+1], ZoneClose): + end = complex(self[0].real, self[0].imag) + closePath = True + else: + end = complex(self[n+1].real, self[n+1].imag) + return (start, end, closePath) class QuickJoint(inkex.Effect): def add_arguments(self, pars): @@ -57,11 +85,6 @@ def add_arguments(self, pars): pars.add_argument('-S', '--featureStart', type=inkex.Boolean, default=False, help='Tab/slot instead of space on the start edge') pars.add_argument('-E', '--featureEnd', type=inkex.Boolean, default=False, help='Tab/slot instead of space on the end edge') - def to_complex(self, command, line): - debugMsg('To complex: ' + command + ' ' + str(line)) - - return complex(line[0], line[1]) - def draw_parallel(self, start, guideLine, stepDistance): polR, polPhi = cmath.polar(guideLine) polR = stepDistance @@ -79,13 +102,6 @@ def draw_perpendicular(self, start, guideLine, stepDistance, invert = False): debugMsg(cmath.rect(polR, polPhi)) return (cmath.rect(polR, polPhi) + start) - def move(self, lines, point): - debugMsg("- move: " + str(point)) - lines.append(['M', [point.real, point.imag]]) - - def line(self, lines, point): - debugMsg("- line: " + str(point)) - lines.append(['L', [point.real, point.imag]]) def draw_box(self, start, lengthVector, height, kerf): @@ -102,29 +118,25 @@ def draw_box(self, start, lengthVector, height, kerf): cursor = self.draw_parallel(start, lengthEdge, kerf/2) cursor = self.draw_parallel(cursor, heightEdge, kerf/2) - lines = [] - self.move(lines, cursor) + path = QuickJointPath() + path.Move(cursor) cursor += lengthEdge - self.line(lines, cursor) + path.Line(cursor) cursor += heightEdge - self.line(lines, cursor) + path.Line(cursor) cursor -= lengthEdge - self.line(lines, cursor) + path.Line(cursor) cursor -= heightEdge - self.line(lines, cursor) + path.Line(cursor) - lines.append(['Z', []]) + path.close() - return lines + return path - def vectorDraw(self, start, lines, vector): - start = start + vector - self.line(lines, start) - return start def draw_tabs(self, path, line): cursor, segCount, segment, closePath = self.get_segments(path, line, self.numtabs) @@ -141,32 +153,32 @@ def draw_tabs(self, path, line): debugMsg("draw_tabs; tabLine=" + str(tabLine) + " spaceLine=" + str(spaceLine) + " segment=" + str(segment)) drawTab = self.featureStart - newLines = [] + newLines = QuickJointPath() - # When handling first line, need to set M back + # First line is a move or line to our start point if isinstance(path[line], Move): - self.move(newLines, cursor) + newLines.Move(cursor) else: - self.line(newLines, cursor) + newLines.Line(cursor) for i in range(segCount): debugMsg("i = " + str(i)) if drawTab == True: debugMsg("- tab") - cursor = self.vectorDraw(cursor, newLines, tabOut) - cursor = self.vectorDraw(cursor, newLines, tabLine) - cursor = self.vectorDraw(cursor, newLines, tabIn) + newLines.line(tabOut) + newLines.line(tabLine) + newLines.line(tabIn) else: if i == 0 or i == segCount - 1: debugMsg("- endspace") - cursor = self.vectorDraw(cursor, newLines, endspaceLine) + newLines.line(endspaceLine) else: debugMsg("- space") - cursor = self.vectorDraw(cursor, newLines, spaceLine) + newLines.line(spaceLine) drawTab = not drawTab if closePath: - newLines.append(['Z', []]) + newLines.close return newLines def add_new_path_from_lines(self, lines, line_style): @@ -183,17 +195,8 @@ def get_segments(self, path, line, num): if not self.featureStart: segCount = segCount + 1 if not self.featureEnd: segCount = segCount + 1 - # Calculate the start and end of the edge we've been told to modify. - start = to_complex(path[line]) - # If the next point in the path closes the path, go back to the start. - end = None - closePath = False - if isinstance(path[line+1], ZoneClose): - end = to_complex(path[0]) - closePath = True - else: - end = to_complex(path[line+1]) - + start, end, closePath = QuickJointPath(path).get_line(line) + # Calculate the length of each feature prior to kerf compensation. # Here we divide the specified edge into equal portions, one for each feature or space. @@ -270,5 +273,8 @@ def effect(self): elif self.activetab == 'slotpage': newPath = self.draw_slots(p) + + + if __name__ == '__main__': QuickJoint().run() From f6225d044af1b8257c94642dffe7d835d5ed5107 Mon Sep 17 00:00:00 2001 From: alan Date: Thu, 20 Oct 2022 14:24:29 -0400 Subject: [PATCH 17/17] Fix get_line --- quickjoint.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/quickjoint.py b/quickjoint.py index 130d0d5..4594ee0 100644 --- a/quickjoint.py +++ b/quickjoint.py @@ -61,15 +61,16 @@ def line(self, vector): def get_line(self, n): '''Return the end points of the nth line in the path as complex numbers, as well as whether that line closes the path.''' - start = complex(self[n].real, self[n].imag) + + start = complex(self[n].x, self[n].y) # If the next point in the path closes the path, go back to the start. end = None closePath = False if isinstance(self[n+1], ZoneClose): - end = complex(self[0].real, self[0].imag) + end = complex(self[0].x, self[0].y) closePath = True else: - end = complex(self[n+1].real, self[n+1].imag) + end = complex(self[n+1].x, self[n+1].y) return (start, end, closePath) class QuickJoint(inkex.Effect):