a freecad plugin to turn designs into lasercuttable panels
0

Configure Feed

Select the types of activity you want to include in your feed.

Python 69.3%
Shell 3.9%
PowerShell 3.7%
Batchfile 0.2%
Other 23.0%
7 1 0

Clone this repository

https://tangled.org/simmarith.pds.simmarith.de/dxf-decomposer https://tangled.org/did:plc:s7e732otif3oye7risx7c4ij
git@knot.simmarith.de:simmarith.pds.simmarith.de/dxf-decomposer git@knot.simmarith.de:did:plc:s7e732otif3oye7risx7c4ij

For self-hosted knots, clone URLs may differ based on your setup.


README.md

Panel Decomposer for FreeCAD#

A FreeCAD workbench that turns selected faces of a Body or Part into laser-cut panels. It adds complementary finger joints where selected planar faces share a convex or concave, straight, right-angle edge. Selected cylindrical fillets become living hinges, unfolded and joined to their selected tangent panels as a continuous blank. The layout exports as a millimetre DXF with separate outline, hinge and label layers.

Install#

Use FreeCAD 0.20.2 or newer with Python 3. The addon uses only FreeCAD's bundled Python, Qt and Part modules; no pip dependencies are needed to run it.

Close FreeCAD, then extract dist/PanelDecomposer-0.1.0.zip anywhere or clone this repository. Run the installer from the resulting PanelDecomposer folder:

Platform Install
Linux Run bash install-linux.sh in a terminal.
macOS Run bash install-macos.command in Terminal. For double-click installation, run chmod +x install-macos.command, then open it in Finder.
Windows Double-click install-windows.cmd. It uses the PowerShell included with Windows 10/11.

These scripts install the addon for your current user, without administrator rights, Python or additional downloads. Restart FreeCAD and choose Panel Decomposer from the workbench selector when installation finishes.

FreeCAD 1.1 and later use versioned profiles such as FreeCAD/v1-1/. The installers select the newest existing numeric version directory. If you use multiple FreeCAD versions, specify the active version's Mod directory or use the FreeCAD macro below to get the exact destination from the application.

On Linux, the installer uses an existing FreeCAD user directory when available, including legacy, Flatpak and Snap locations, or defaults to ${XDG_DATA_HOME:-~/.local/share}/FreeCAD/Mod. On macOS, it uses ~/Library/Application Support/FreeCAD/Mod or an existing legacy ~/Library/Preferences/FreeCAD/Mod directory. On Windows, it uses %APPDATA%\FreeCAD\Mod. If you have multiple installations or a custom profile, pass its Mod directory explicitly. The installer prints the destination; --dry-run (PowerShell: -DryRun) shows what it would do without changing files. Existing FREECAD_USER_DATA or FREECAD_USER_HOME environment overrides are respected; an explicit Mod directory takes precedence.

# Linux: inspect the default or specify a different FreeCAD profile.
bash install-linux.sh --dry-run
bash install-linux.sh --mod-dir "/path/to/FreeCAD/Mod"

# macOS: specify a different FreeCAD profile.
bash install-macos.command --mod-dir "/path/to/FreeCAD/Mod"
# Windows: inspect the default or specify a different FreeCAD profile.
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\install-windows.ps1 -DryRun
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\install-windows.ps1 -ModDir "D:\FreeCAD profile\Mod"

Windows' launcher permits this local script to run for that PowerShell process; it does not change your system execution policy. If your device's managed policy blocks scripts, use the manual installation below.

Rerunning an installer updates the addon. A previous installation is moved into PanelDecomposer-backups, beside the Mod directory, before replacement. The backup path is printed. Other addons are left alone. To restore a backup, close FreeCAD, move the current Mod/PanelDecomposer aside and copy the backed-up PanelDecomposer folder into Mod. To uninstall, close FreeCAD and remove only Mod/PanelDecomposer. The installers refuse to replace an unrelated folder or a development symlink/junction.

For manual installation, extract the addon ZIP into FreeCAD's user Mod directory, or copy this repository there as a folder named PanelDecomposer.

If the workbench is missing after installing, open Install-PanelDecomposer.FCMacro from the extracted addon folder in FreeCAD (File → Open), then choose Macro → Execute macro. It installs into the exact directory returned by the running FreeCAD application and checks that the workbench registers. Restart FreeCAD afterward. This also works on Linux and Windows.

For example, FreeCAD 1.1 on macOS can return ~/Library/Application Support/FreeCAD/v1-1/; its addon directory is ~/Library/Application Support/FreeCAD/v1-1/Mod, not the unversioned FreeCAD/Mod.

Find the correct user directory in FreeCAD's Python console:

import FreeCAD, os
print(os.path.join(FreeCAD.getUserAppDataDir(), "Mod"))

The resulting tree should be Mod/PanelDecomposer/InitGui.py, with panel_decomposer/, resources/ and package.xml alongside it. This is a manual installation package; it has not been published to the FreeCAD Addon Manager.

Use#

  1. Open or create a solid whose exterior faces describe the desired finished shape. Select the Body/Part, or Ctrl-select specific panel faces on one object.
  2. Click Decompose into panels…. With an object selected, planar faces are checked by default. With faces selected, only those faces are checked.
  3. Choose the panels in the face list. The 3D model tab updates immediately: blue faces are selected panels, green faces are selected hinges, and orange is the active face. Drag to rotate, right-drag to pan, and scroll to zoom. Click a face to locate its row, or double-click to check/uncheck it. See through model reveals selected rear and internal surfaces; turn it off for a solid view. Fit model recenters the view and Isometric resets its orientation. Clicking a row also highlights it on the source in FreeCAD. Cylindrical fillets are opt-in: check the fillet and its two tangent neighbors to produce one connected, flexible blank. Use face selection copies the current 3D face selection into the list.
  4. Set the material thickness, desired finger width, fit clearance and laser kerf. Adjust living-hinge cuts and sheet dimensions as needed.
  5. Click Generate preview and inspect the Cutting layout tab and any messages. Switch back to 3D model to inspect the generated cuts and finger joints in red on the source surfaces, with hinge slits in lime wrapped around the fillets. You can add a static cut-path preview to the document, or export directly.
  6. Click Export DXF…. In your laser software, check that dimensions are in mm, assign CUT and HINGE to cutting, and assign LABEL to engraving or disable it.

The 3D visualizer shows the selected design surfaces on the source geometry. After a successful preview, it also projects the actual cut paths, including kerf compensation, onto those surfaces. Joined hinge boundaries have no cut lines. Changing selection or settings removes the projection and disables the old cutting layout until regenerated. Rotating the view or highlighting a face keeps the projection. The dialog is modeless so you can still inspect the source in FreeCAD. It captures the source geometry when opened; reopen it after changing the model. Added document previews are static snapshots, with the source reference, face numbers and settings stored on them. The source geometry is not modified.

Geometry and settings#

Design surfaces and thickness. Select one design surface per panel. Faces describe the outside dimensions of the finished object and sheet material extends inward. The source can be a filled solid; this tool constructs its panel shell. For a hollow model, avoid selecting both the inner and outer face of each wall. Thickness is specified explicitly rather than inferred from a model.

Finger joints. Both sides use the same odd number of fingers, with width chosen near your target value and adjusted to span the shared edge. Convex corners use alternating recesses one material thickness deep. Concave corners use complementary tabs extending one thickness beyond each face boundary to fill the inside corner. The assembled design dimensions are preserved; concave panel blanks grow to include these tabs. Where a selected perpendicular end panel meets the concave edge, tabs stop one thickness short of that end to leave room for the end panel. Three-panel corners are assigned consistently through stable face ordering. Joint clearance increases convex notch width or decreases concave tab width by the specified total amount. Select both mating faces to create a pair.

Living hinges. Only rectangular cylindrical patches with two straight generator edges and two circular end edges are supported. The flat band width is the bend angle in radians multiplied by the neutral radius. For an outer surface of radius R, the neutral radius is R - (1 - k) * thickness; for an inner surface it is R + k * thickness. k = 0.5 places the neutral layer at mid-thickness. This is a geometric bend-length estimate; slit patterns and material affect the actual bend. The slit rows run parallel to the cylinder axis, with alternating bridge positions. End margins, bridges and row spacing retain material around the cuts. The band and tangent neighbors are joined before outline export, so there are no cuts through their connecting boundaries. A band selected on its own exports as a separate piece with a message that its tangent neighbors are missing.

Kerf. Enter the laser's full measured cut width. Outline toolpaths are offset outward by half the kerf; holes are offset inward. Living-hinge slits are single centerline cuts, whose width is the laser kerf. Set kerf to zero here if your laser software already compensates the outlines. Clearance and kerf are separate settings. Cut a small joint/hinge coupon in your actual stock before committing a full sheet.

Layout. A deterministic shelf layout uses 90° rotations, margins and spacing. It exports one sheet and reports an error when the pieces do not fit. This is a simple arrangement, not an optimal nesting solver; increase the sheet size or export smaller selections when necessary. It does not consider grain direction.

DXF. ASCII R2000 DXF with $INSUNITS = 4 (mm). Outlines and holes are closed LWPOLYLINE entities on CUT, slit cuts are open two-point LWPOLYLINE entities on HINGE, and optional part names are TEXT on LABEL. Curves are sampled to the configured chord tolerance. There are no sheet-border cuts or duplicate cuts along joined hinge boundaries. Writes replace the destination atomically.

Current limits#

  • Finger joints support convex and concave 90° planar corners sharing exact source topology. Other angles and curved end edges are reported without finger joints. Separate touching objects are not matched by proximity. Concave tabs that cannot fit beside selected end panels are rejected; increase finger width or reduce thickness.
  • Spherical, conical, toroidal and general spline faces are not unfoldable here. Cylindrical fillets with holes or trimmed ends, and full cylinders, are rejected.
  • Closed hinge loops, overlapping unfolded faces, and sharp joins within a connected hinge blank are rejected; change the fillet selection to create a seam.
  • Holes in planar panels are preserved. Joint depth is checked against the available material. Degenerate features and contours that collapse under kerf are rejected.
  • Unsupported curved edges do not receive automatic end joints or end caps. A filleted enclosure can need separate end-attachment design beyond this addon.
  • This version has no per-edge phase overrides, material library, assembly animation, multi-sheet nesting or automatic updates after source edits.

Examples#

examples/finger-joint-box.FCStd and its DXF demonstrate all six faces of an 80 × 60 × 40 mm box using 3 mm material. examples/living-hinge-corner.FCStd and its DXF demonstrate an 8 mm fillet and its two tangent panels. The source object's label specifies the faces to select for the hinge example. Example DXFs omit labels.

Regenerate the examples with a Python that can import FreeCAD:

PYTHONPATH=/usr/lib/freecad-python3/lib:. python3 examples/create_examples.py

Python API#

Run from FreeCAD's Python console, or a compatible standalone Python:

from panel_decomposer.engine import decompose
from panel_decomposer.model import Settings
from panel_decomposer.dxf import export_dxf

body = FreeCAD.ActiveDocument.getObject("Body")
result = decompose(body.Shape, [1, 2, 3], Settings(thickness=3, kerf=0.15))
export_dxf(result, "/path/to/panels.dxf")
print(result.joint_count, result.hinge_count, result.warnings)

Face numbers are 1-based. Results contain flat OpenCASCADE regions, compensated cut paths, hinge lines and layout dimensions.

Development and validation#

Tests need FreeCAD's Python bindings, pytest and ezdxf. The last two are test-only dependencies. On Debian, install freecad-python3 python3-pytest python3-ezdxf and run:

python3 -m pytest -q
python3 tools/build_addon.py

For other installations, set FREECAD_LIB to the directory containing FreeCAD.so or FreeCAD.pyd when running tests. Use the same Python version as FreeCAD. Validation covers 3D assembly of convex and concave panels, including selected end panels at concave corners, clearance, connected hinge unfolding, transformed source placement, retained hinge bridges, hole kerf compensation, sheet bounds, invalid geometry/settings, DXF import/audit and atomic export failure. An installed-workbench smoke test in the FreeCAD 0.20.2 application also verified workbench registration, Body selection, the command dialog, preview generation, document cut paths and DXF export. Newer versions should be checked in the target installation.

Installer tests use isolated profiles to verify installation from both a checkout and the release ZIP, updates and backup restoration, custom paths and profiles, and refusal to replace unrelated folders or links. Linux and macOS shell paths are exercised on Linux; the Windows script is exercised with PowerShell on Linux. Native macOS and Windows execution has not been verified. To include the PowerShell tests, install pwsh or set PANEL_DECOMPOSER_PWSH to its executable. Versioned profile detection includes a regression test for FreeCAD 1.1's macOS v1-1 directory. The in-application installer macro was also exercised in FreeCAD 0.20.2 with a custom versioned profile, verifying installation, registration and workbench activation.

Licensed under the MIT license.