From c2dd7425e984ad1449392e1fe79cd692650d0e0d Mon Sep 17 00:00:00 2001 From: JohnHyslop <49624325+JohnHyslop@users.noreply.github.com> Date: Sat, 13 Dec 2025 18:13:39 +1100 Subject: [PATCH 1/5] Create README.md --- StitchCut/README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 StitchCut/README.md diff --git a/StitchCut/README.md b/StitchCut/README.md new file mode 100644 index 0000000..8c3591a --- /dev/null +++ b/StitchCut/README.md @@ -0,0 +1,27 @@ +# StitchCut Macro + +The StitchCut macro creates evenly spaced stitch cuts along a selected line in a sketch, +primarily for sheet metal flat patterns to allow easier hand folding. + +## Features +- Start & end offset from edges +- Automatic cut length calculation +- User-defined number of cuts +- Inserts cuts directly into the active sketch + +## Usage +1. Enter **edit mode** on a sketch. +2. Select the line to apply stitch cuts to. +3. Run the macro. +4. Enter: + - Start & End Offset + - Number of cuts +5. The original line is replaced with stitch cuts. + +## Author +John Hyslop +## FreeCAD Version +Tested on FreeCAD 1.02 + +## License +Free for personal and educational use. Please credit the author. From 780feb92e524f79f17ee93c6f3feca48fd4eec7e Mon Sep 17 00:00:00 2001 From: JohnHyslop <49624325+JohnHyslop@users.noreply.github.com> Date: Sat, 13 Dec 2025 18:15:51 +1100 Subject: [PATCH 2/5] Add files via upload --- StitchCut/StitchCut.py | 142 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 StitchCut/StitchCut.py diff --git a/StitchCut/StitchCut.py b/StitchCut/StitchCut.py new file mode 100644 index 0000000..76cefa6 --- /dev/null +++ b/StitchCut/StitchCut.py @@ -0,0 +1,142 @@ +""" +StitchCut.py + +Author: John Hyslop +Description: + This FreeCAD macro allows you to create evenly spaced "stitch cuts" along a selected + straight line in a sketch. The user can specify the start & end offsets, gap between cuts, + and number of cuts. The macro will calculate the cut lengths and insert them directly + into the sketch. + + Created with a little extra help from ChatGPT. +""" + +import FreeCAD, FreeCADGui +from PySide import QtGui +import math, Part + +# --- Dialog --- +class StitchCutDialog(QtGui.QDialog): + def __init__(self, line_length, parent=None): + super().__init__(parent) + self.setWindowTitle("Stitch Cut Parameters") + self.line_length = line_length + + self.edge_offset_edit = QtGui.QLineEdit("3") # Changed label + self.gap_edit = QtGui.QLineEdit("3") + self.num_cuts_edit = QtGui.QLineEdit("5") + self.cut_length_display = QtGui.QLabel("0") + + layout = QtGui.QFormLayout() + layout.addRow("Start & End Offset:", self.edge_offset_edit) + layout.addRow("Gap between cuts:", self.gap_edit) + layout.addRow("Number of Cuts:", self.num_cuts_edit) + layout.addRow("Calculated Cut Length:", self.cut_length_display) + + buttons = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel) + buttons.accepted.connect(self.accept) + buttons.rejected.connect(self.reject) + layout.addWidget(buttons) + + self.setLayout(layout) + + # update calculation dynamically + self.edge_offset_edit.textChanged.connect(self.update_cut_length) + self.gap_edit.textChanged.connect(self.update_cut_length) + self.num_cuts_edit.textChanged.connect(self.update_cut_length) + self.update_cut_length() + + def update_cut_length(self): + try: + edge_offset = float(self.edge_offset_edit.text()) + gap = float(self.gap_edit.text()) + num = int(self.num_cuts_edit.text()) + usable = self.line_length - 2*edge_offset - (num - 1) * gap + if usable <= 0: + self.cut_length_display.setText("N/A") + else: + self.cut_length_display.setText(f"{usable/num:.3f}") + except: + self.cut_length_display.setText("Error") + + def getValues(self): + try: + edge_offset = float(self.edge_offset_edit.text()) + gap = float(self.gap_edit.text()) + num = int(self.num_cuts_edit.text()) + usable = self.line_length - 2*edge_offset - (num - 1) * gap + if usable <= 0: + return None + cut_length = usable / num + return edge_offset, gap, num, cut_length + except: + return None + +# --- Get selected line --- +def get_selected_line(): + sel = FreeCADGui.Selection.getSelectionEx() + if len(sel) != 1: + QtGui.QMessageBox.critical(None, "Error", "Select exactly one line in a sketch.") + return None, None + sk = sel[0].Object + if sk.TypeId != "Sketcher::SketchObject": + QtGui.QMessageBox.critical(None, "Error", "Selection is not a sketch.") + return None, None + if len(sel[0].SubElementNames) != 1: + QtGui.QMessageBox.critical(None, "Error", "Select exactly one edge.") + return None, None + edge_name = sel[0].SubElementNames[0] + idx = int(edge_name.replace("Edge","")) - 1 + geo = sk.Geometry[idx] + if geo.TypeId != 'Part::GeomLineSegment': + QtGui.QMessageBox.critical(None, "Error", "Selected geometry is not a straight line.") + return None, None + return sk, idx + +# --- Main macro --- +def stitch_cut(): + sk, idx = get_selected_line() + if not sk: + return + + line = sk.Geometry[idx] + p1 = line.StartPoint + p2 = line.EndPoint + + vec = p2.sub(p1) + length = vec.Length + direction = vec.normalize() + + dlg = StitchCutDialog(length) + if dlg.exec_() != QtGui.QDialog.Accepted: + return + + values = dlg.getValues() + if not values: + QtGui.QMessageBox.critical(None, "Error", "Invalid parameters, cuts won't fit.") + return + edge_offset, gap, num_cuts, cut_length = values + + # Remove original line + sk.delGeometry(idx) + + # Add stitch cuts + for i in range(num_cuts): + start_dist = edge_offset + i*(cut_length + gap) + end_dist = start_dist + cut_length + if end_dist > length - edge_offset: + end_dist = length - edge_offset + ptA = FreeCAD.Vector(p1.x + direction.x*start_dist, + p1.y + direction.y*start_dist, + p1.z + direction.z*start_dist) + ptB = FreeCAD.Vector(p1.x + direction.x*end_dist, + p1.y + direction.y*end_dist, + p1.z + direction.z*end_dist) + sk.addGeometry(Part.LineSegment(ptA, ptB), False) + + sk.Document.recompute() + QtGui.QMessageBox.information(None, "Done", "Stitch cuts applied!") + +# --- Run --- +stitch_cut() + From bdec4d6b0c007448fe710043f3630efc4e883604 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 13 Dec 2025 07:30:04 +0000 Subject: [PATCH 3/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- StitchCut/README.md | 2 +- StitchCut/StitchCut.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/StitchCut/README.md b/StitchCut/README.md index 8c3591a..682644c 100644 --- a/StitchCut/README.md +++ b/StitchCut/README.md @@ -1,6 +1,6 @@ # StitchCut Macro -The StitchCut macro creates evenly spaced stitch cuts along a selected line in a sketch, +The StitchCut macro creates evenly spaced stitch cuts along a selected line in a sketch, primarily for sheet metal flat patterns to allow easier hand folding. ## Features diff --git a/StitchCut/StitchCut.py b/StitchCut/StitchCut.py index 76cefa6..c0380be 100644 --- a/StitchCut/StitchCut.py +++ b/StitchCut/StitchCut.py @@ -2,8 +2,8 @@ StitchCut.py Author: John Hyslop -Description: - This FreeCAD macro allows you to create evenly spaced "stitch cuts" along a selected +Description: + This FreeCAD macro allows you to create evenly spaced "stitch cuts" along a selected straight line in a sketch. The user can specify the start & end offsets, gap between cuts, and number of cuts. The macro will calculate the cut lengths and insert them directly into the sketch. From 8ccd6caa7b3ec1e352c137d0126e73923ed06718 Mon Sep 17 00:00:00 2001 From: JohnHyslop <49624325+JohnHyslop@users.noreply.github.com> Date: Mon, 15 Dec 2025 13:53:40 +1100 Subject: [PATCH 4/5] [StitchCut] Clarify license to allow commercial use --- StitchCut/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/StitchCut/README.md b/StitchCut/README.md index 682644c..f2e924a 100644 --- a/StitchCut/README.md +++ b/StitchCut/README.md @@ -24,4 +24,6 @@ John Hyslop Tested on FreeCAD 1.02 ## License -Free for personal and educational use. Please credit the author. +Free for personal, educational, and commercial use. + +Please credit the author. From b3f1c24f86bdaee89b6712072efcc1f48ff1f772 Mon Sep 17 00:00:00 2001 From: JohnHyslop <49624325+JohnHyslop@users.noreply.github.com> Date: Mon, 15 Dec 2025 16:29:09 +1100 Subject: [PATCH 5/5] [StitchCut] Update macro metadata and version - Added version 1.0 - License updated to include commercial use - Metadata updated for Addon Manager compatibility --- StitchCut/StitchCut.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/StitchCut/StitchCut.py b/StitchCut/StitchCut.py index c0380be..bd062a4 100644 --- a/StitchCut/StitchCut.py +++ b/StitchCut/StitchCut.py @@ -10,6 +10,22 @@ Created with a little extra help from ChatGPT. """ +# --- Macro Metadata --- +__Name__ = "StitchCut" +__Comment__ = "Creates evenly spaced stitch cuts along a selected line in a sketch, for hand-folding sheet metal." +__Author__ = "John Hyslop" +__Date__ = "2025-12-15" +__Version__ = "1.0" +__License__ = "Free for personal, educational, and commercial use. Please credit the author." +__Web__ = "https://github.com/JohnHyslop/MyFreeCADMacros/StitchCut" +__Wiki__ = "https://wiki.freecad.org/StitchCut" +__Icon__ = "" +__Xpm__ = "" +__Help__ = "Select a line in a sketch, run macro, and define offsets, gap, and number of cuts." +__Status__ = "Stable" +__Requires__ = "FreeCAD >= 1.02" +__Communication__ = "https://github.com/JohnHyslop/MyFreeCADMacros/issues" +__Files__ = "StitchCut.py" import FreeCAD, FreeCADGui from PySide import QtGui