Skip to content

feat: add a Perforation post-processor for Contour steps - #540

Merged
knipknap merged 8 commits into
barebaric:mainfrom
switch87:feat/perforation
Oct 15, 2026
Merged

knipknap merged 8 commits into
barebaric:mainfrom
switch87:feat/perforation

Conversation

@switch87

@switch87 switch87 commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Add a Perforation post-processor for Contour steps: dashed cutting for fold
lines, tear-offs and perforations. The laser fires for a configurable cut
length
and skips a configurable skip length, repeated along every contour of
the workpiece.

Fixes #525.

What's in this PR

  • Perforation transformer for ContourStep: offered by default (disabled)
    alongside the other contour post-processors, with a Perforation settings
    group (Cut Length / Skip Length) in the step's post-processing page.
  • Gaps are computed per-contour in millimetres of arc length, starting with a
    full cut at the start of each contour, and delivered through the existing
    gap machinery — so they work with path optimization, lead-in/out and the
    rest of the contour post-processing stack.
  • Settings are persisted with the step (to_dict/from_dict roundtrip).

Example

On a simple imported contour (a rectangle + circle), enabling Perforation with
cut 2.0 mm / skip 1.0 mm produces 40 gaps along the contours.

{
  "step": "Contour",
  "cut_length_mm": 2.0,
  "skip_length_mm": 1.0,
  "gaps_found": 40
}

Tests

  • rayforge/builtin_addons/rayforge-addon-post/tests/transformers/test_perforation_transformer.py
    — gap centres, clips generation, spec output, serialization (18 passed).
  • rayforge/builtin_addons/rayforge-addon-post/tests/ui_gtk/test_perforation_group.py
    — the settings group widget.

Cuts in dashes: the laser fires for a cut length and is off for a skip
length along every contour, restarting with a full cut at the start of
each contour. The gap centres are placed in millimetres along the
workpiece's contours and handed to the existing tabs gap transform, so
no new raygeo code is needed. Off by default in new and loaded Contour
steps.

Refs barebaric#525
An empty description makes the Docusaurus build fail with
"description" must be a string, breaking the PR Preview step.
@switch87

Copy link
Copy Markdown
Contributor Author

@knipknap Gentle ping, no rush while you're travelling. Eight of my PRs haven't had a review for two days or more: #540, #541, #542, #547, #553, #554, #555 and #556. All of them merge cleanly into main and their CI is green. GitHub won't let me open more PRs at this count, so if one of them isn't wanted, feel free to close it. In the meantime I'll keep further work on the issues. If anything would make reviewing easier, such as splitting a PR or adding a test plan, let me know.

@knipknap

Copy link
Copy Markdown
Contributor

Hi @switch87,

Thanks for all the PRs lately! I really like the ideas you're bringing to the project.

Honestly, it looks a bit like you might be leaning heavily on AI to generate these PRs. I totally get it (and I use AI tools heavily too!), but it's creating a bit of a bottleneck for me.

The issue with raw AI output is that it often misses the bigger picture of the project's architecture and introduces UI issues. I'm finding myself spending a ton of time understanding the code and trying to make it fit the codebase. It sometimes kind of feels like I'm debugging the AI rather than reviewing a PR.

A while ago I was on a vacation and created the same situation for myself: Using AI, in just a few hours I created many PRs that I thought were fine, and coming back home reviewing them properly I found so many issues that it took me two weeks to get most of them merged - and that also caused overlapping issues, i.e. fixing one PR caused conflicts in another. It surprised me that the bulk of the work was yet ahead.

I really like your ideas and want to keep merging your stuff, but I need to ask that before opening or updating a PR, could you spend some time manually reviewing the code to make sure it actually fits the existing architecture? And ideally, they parallel PRs should not target the same parts of the app, as that makes recurring conflicts more likely. Also note that force-pushing after a review means I have to review the whole PR again instead of just corrections, so it is better to avoid that. I can squash PRs on merge if it makes sense to keep the history clean.

I will continue to go through your already opened PRs, but am afraid that in a world where reviewing and refining takes more time than writing code, this current approach is not sustainable.

The new strings stay wrapped in _(); the .po/.pot files are updated
once before each release.
@switch87

Copy link
Copy Markdown
Contributor Author

Thanks for the honest feedback, and for still taking the time to review. You're right, and I'm changing how I work:

I won't open new PRs until the current ones are worked through. If any of the open ones isn't a direction you want for Rayforge, feel free to just close it.

PerforationTransformer declared SPEC_NAME "tabs" and is registered
before TabOpsTransformer, so the batch progress for every tabs spec
was labelled "Perforation". Leave the spec name to the Tabs
transformer.

Refs barebaric#525
@switch87

Copy link
Copy Markdown
Contributor Author

I went through this one again against the architecture and pushed two small follow-up commits on top (no force-push):

  • be8c16b: PerforationTransformer declared SPEC_NAME "tabs" and is registered before TabOpsTransformer, so the progress detail for every tabs spec showed "Perforation". It no longer claims the spec name; there's a test for the label.
  • e2e73ef: the Cut/Skip rows now use the transformer's MIN_LENGTH instead of a repeated 0.01.

The .po/.pot changes were already taken out in 1bab19e. The rest still follows what you described on #525: a gap-mode TabsSpec with gap centres every cut + skip, restarting per contour, off by default.

Add two screenshot targets: operations:perforation loads a new
perforation.ryp asset (a rectangle and a circle on a plywood stock,
Perforation enabled at 1.0 mm cut / 0.5 mm skip) and captures a
close-up of the dashed toolpath; step-settings:contour:post:perforation
opens the post-processing page with the Perforation group enabled and
expanded. Regenerate step-settings-contour-post.webp so it includes
the new Perforation row.
Turn the bullet-heavy page into flowing prose in English and all
translations, explain where the post-processor lives and how the
pattern behaves, and show both the settings UI and the resulting
dashed cut on the canvas.
@knipknap

Copy link
Copy Markdown
Contributor

Thank you for this very useful feature!

@knipknap
knipknap merged commit 76a4b14 into barebaric:main Oct 15, 2026
32 checks passed
@switch87
switch87 deleted the feat/perforation branch October 15, 2026 13:21

This branch was successfully deployed

1 active deployment
pypi — 972370d0 Deployed Oct 15, 2026 by knipknap via Build and Publish Wheel #2329
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Perforation mode for Contour steps (cut length + skip length)

2 participants