Skip to content

Uniform mm-spacing spiral toolpath (Issue #22)#23

Merged
CyberCraftLab merged 3 commits into
mainfrom
fix/equal-frame-spacing-along-toolpath
May 19, 2026
Merged

Uniform mm-spacing spiral toolpath (Issue #22)#23
CyberCraftLab merged 3 commits into
mainfrom
fix/equal-frame-spacing-along-toolpath

Conversation

@CyberCraftLab

Copy link
Copy Markdown
Owner

Fixes #22.

Summary

  • Replace FramesPerLayer (count per revolution) with FrameSpacingMm (arc-length distance between consecutive frames) across the model, dialog, builders, and call sites. Sampling by mm gives uniform bead density regardless of part shape.
  • Rewrite SpiralInterpolator around a two-step plan: build one continuous on-surface spiral curve, then walk it bottom-to-top at FrameSpacingMm. Helical pitch = the user's LayerHeight (one full turn per LayerHeight of Z rise).
  • Surface fidelity: re-slice the source brep/mesh internally at 0.5 mm pitch (independent of the print layer height) so chord blends between consecutive contours stay close to the source surface.
  • Angular fidelity: sample each contour by ray-cast from its centroid at the target spiral angle, picking the farthest intersection. This handles non-convex / wavy contours correctly where arc-length-parameter sampling would cut across the part interior and create fan/spoke artefacts.
  • Skirt + base also migrated: SampleSkirtFrames and BaseBuilder derive sample counts from perimeter / spacing, so every closed loop prints at the same bead density as the spiral.
  • Settings: legacy FramesPerLayer keys in existing settings.json files are silently dropped on load (no math-correct conversion exists without per-part perimeter); the new field defaults to 10.0 mm.

What got cleaned up along the way

  • Removed dead AlignSeamPoints and AlignContourDirections helpers — ray-cast sampling ignores contour parameterization and winding, so both were no-ops (and used to mutate the caller's contour list as a hidden side effect).
  • Removed unused degree parameter from CreateSpiralCurve (always polyline now).
  • Refreshed stale StartAngle comment in Parameters.cs.
  • Polyline (not NURBS) visualization curve so the baked red curve matches the actual robot path point-for-point — a degree-3 fit would smooth between points and overshoot the surface.

Test plan

  • Builds clean: dotnet build -c Debug, 0 warnings / 0 errors
  • Smoke tested in Rhino on a wavy organic mesh — points sit on the surface, spiral is monotonic in Z, frame spacing visually uniform
  • Try on a tall thin vase
  • Try on a part with overhangs / concavities to confirm no Z-zigzag
  • Verify skirt + base layers print at matching bead density

Follow-up (separate PR)

Dead PrintabilityAnalyzer + PrintabilityResult + MinLayerBondRatio field are unreferenced and would need rework for the new mm-spacing model. Flagged as a follow-up task; not in this PR.

🤖 Generated with Claude Code

CyberCraftLab and others added 3 commits May 19, 2026 18:50
Replace FramesPerLayer (count) with FrameSpacingMm (arc-length distance)
across the model, dialog, builders, and call sites. The old normalized-
parameter sampling produced uneven physical spacing whenever contour
perimeters varied; the new model gives uniform bead density regardless
of part shape.

SpiralInterpolator rewritten around a two-step plan: build one
continuous on-surface spiral curve, then walk it from bottom to top at
FrameSpacingMm. Helical pitch = the user's LayerHeight (one full turn
per LayerHeight of Z rise). Surface fidelity comes from two changes:
re-slicing the source brep/mesh internally at 0.5 mm pitch
(independent of print layer height), and sampling each contour by
ray-cast from its centroid at the target spiral angle — which handles
non-convex / wavy contours correctly where arc-length parameter
sampling cut across the part interior.

Skirt and base contours also migrated: SampleSkirtFrames and
BaseBuilder now derive sample count from perimeter / spacing so every
closed loop prints at consistent bead density.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AddCurvePoints used polyline vertices for polylines and a hardcoded
2 mm step for smooth curves. Replaced with uniform DivideByLength
resampling at FrameSpacingMm so layer-mode toolpaths (outer contour +
bracing zigzag) print at the same bead density as the spiral.

Closed curves get the duplicate seam tick trimmed so frame tangents
don't degenerate at the seam.

Base infill remains on vertex sampling — its U-turn corners are
direction changes the robot must hit exactly, so resampling would
round them off. If uniform spacing is wanted there too, that's a
follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ion, dedup helpers

Spiral toolpath (Issue #22):
- Replace per-contour-centroid ray-cast sampler with arc-length parameter
  sampling. Ray-cast was correct on convex contours but short-circuited
  across the interior on multi-lobe / wavy non-convex shapes. Arc-length
  parameterization walks the actual perimeter.
- Restore AlignContourDirections + AlignSeamPoints, but anchor seam
  alignment to a SHARED centroid (mean of all per-layer centroids) so
  parameter t=0 maps to the same angular column on every contour.
- Add constrained lateral projection: each chord-blend sample is
  projected onto the brep/mesh surface, but only when the closest
  surface point is within LayerHeight/2 in Z. Steep walls get hugged;
  near-horizontal regions fall back to chord (the price of staying on
  a printable monotonic-Z spiral).

Sinusoidal bracing:
- Take an optional shared centroid for seam alignment so the cosine
  peaks stack vertically across layers instead of wandering. Phase
  stays arc-length-based so peaks remain evenly distributed along
  each layer's perimeter.
- Panel computes the shared centroid once and passes it to both the
  toolpath generation loop and the preview-arrow bake.

Cleanup from review pass:
- Promote SpiralInterpolator.ComputeSharedCentroid to public, delete
  the duplicate in CCL_Clay3DPPanel.
- Replace magic 10000.0 (seam ray distance) and 1e-3 (dedup tolerance)
  with named constants.
- RefineContoursIfPossible always returns a fresh list now — callers
  mutate the result via Align* and must not corrupt input contour data.
- Strip narration comments that just restated the code.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@CyberCraftLab CyberCraftLab merged commit 6b47c35 into main May 19, 2026
2 checks passed
@CyberCraftLab CyberCraftLab deleted the fix/equal-frame-spacing-along-toolpath branch May 19, 2026 19:52
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.

Frame spacing along toolpath is not uniform

1 participant