Non-Planar controls¶
Status: PROPOSED
The control set and workflows come from docs/ui/ui-plan.md:181–195,223–227,277–285.
Only Enable reaches generation today. Every other non-planar field,
region operation, and non-planar overlay on this page is PROPOSED.
The panel is deliberately first in Prepare: it states the product decision before conventional Process values. It is expanded by default.
Control-by-control honesty¶
| Control | User-facing meaning | Range / choices | Engine or host hook | Honesty |
|---|---|---|---|---|
| Enable | Turn non-planar variation on for generation | Off / On | Existing NpsGcodeGenParams.enableNonPlanar |
HOW IT IS — the current checkbox binds EnableNonPlanar (src/SlicerApp/MainWindow.axaml:47–50), and the host packs it as 0 / 1 (src/Nps.EngineHost/EngineSession.cs:336–352) |
| Maximum surface angle | Limit surfaces eligible for non-planar finishing | 0–75° | New SetNonPlanarParams.maxSurfaceAngleDeg |
PROPOSED |
| Maximum amplitude | Cap toolpath Z deviation | millimetres | New SetNonPlanarParams.maxAmplitudeMm |
PROPOSED |
| Thickness envelope | Blend the non-planar transition through adjacent layers | millimetres | New SetNonPlanarParams.thicknessEnvelopeMm |
PROPOSED |
| Nozzle clearance radius | Radial collision envelope around the nozzle | millimetres | New collisionRadiusMm |
PROPOSED |
| Gantry clearance height | Vertical collision envelope | millimetres | New collisionHeightMm |
PROPOSED |
| Detection mode | Choose how candidate regions originate | Auto / Paint / Full | New detectionMode |
PROPOSED |
| Seam policy | Choose seam placement policy | Aligned / Nearest / Random / Painted | New seamPolicy |
PROPOSED |
| Detect regions | Compute automatic candidates | Button | New DetectNonPlanarRegions + GetNonPlanarRegions |
PROPOSED |
| Paint regions | Enter viewport brush mode | Button / toolbar toggle / B |
Host paint state; commit through new ApplyRegionPaintStrokes |
PROPOSED |
| Region list | Show each region and its source | Auto / Painted badges | New GetNonPlanarRegions |
PROPOSED |
| Per-region override | Change amplitude/policy for one region | Field-level deltas | New SetNonPlanarRegionOverride |
PROPOSED |
| Remove region | Delete a selected region | Action in Regions tab | New RemoveNonPlanarRegion |
PROPOSED |
What Enable means today
The current route calls GenerateGcode, whose host facade is explicitly
named GenerateDemoToolpath and documented as not a production slice
(src/Nps.EngineHost/EngineSession.cs:330–336,363–389). Enable proves the
parameter path; it does not make the proposed angle, amplitude, clearance,
detection, or region controls real.
When Enable is off, all dependent controls are disabled with the visible reason
Enable Non-Planar first. Values may remain displayed, but they do not imply
that the engine consumed them.
Planned parameter object¶
PROPOSED — the new numeric/policy fields travel together in an additive POD:
NpsNonPlanarParams
maxSurfaceAngleDeg
maxAmplitudeMm
thicknessEnvelopeMm
collisionRadiusMm
collisionHeightMm
detectionMode
seamPolicy
reserved[8]
The reserved tail follows the additive ABI policy. The exact binary layout is a developer contract; users see units, ranges, and disabled reasons rather than ABI field names.
Region detection and painting¶
flowchart TD
E["Enable Non-Planar"] --> M{"Detection mode"}
M -->|Auto / Full| D["Detect regions"]
M -->|Paint| P["Enter paint mode"]
D --> L["Region list: auto badge"]
P --> B["LMB paint · Shift+LMB erase · Esc exit"]
B --> C["Commit strokes"]
C --> L2["Region list: painted badge"]
L --> O["Optional per-region override"]
L2 --> O
O --> R["Re-slice"]
Detect¶
PROPOSED — Detect is enabled only when a model is loaded and Non-Planar is on. It runs detection with the panel parameters, then replaces/updates the region list. Every row shows:
- region name/id;
autoorpaintedsource badge;- affected plate/object;
- inherited versus overridden values;
- a focus action that opens the Regions inspector.
Detection failure keeps the prior list and reports the engine error in status and Activity. The UI does not show a fake successful empty list.
Paint¶
PROPOSED — Paint can be entered from the panel, toolbar, or B:
| Gesture / control | Effect |
|---|---|
| Left-drag on mesh | Add eligible faces to the active region |
| Shift + left-drag | Erase faces from the region |
| Radius slider | Change brush footprint |
Esc |
Exit paint mode without triggering another bare-key action |
| Commit | Send accumulated strokes through ApplyRegionPaintStrokes |
The viewport uses existing mesh geometry queries for hit geometry
(GetVertexPositions / GetTriangleIndices exist at
src/Nps.EngineHost/NpsAbi.cs:309–316). The paint-stroke commit and region-mask
overlay are PROPOSED.
Regions inspector¶
PROPOSED — the Regions tab is the full editor. It mirrors the compact Prepare list and adds focus, override, delete, and re-detect actions. Edits mark the current generated path dirty; they do not recolor an old path as if it had been regenerated.
Planned non-planar overlays¶
| Color-by id | Shows | Source | Honesty |
|---|---|---|---|
region-mask |
Planar bulk versus non-planar finish regions | New region data, applied through the existing overlay pipeline | PROPOSED |
nonplanar-amplitude |
Per-move Z deviation / amplitude | New ComputeNonPlanarFields, then existing heatmap application |
PROPOSED |
collision-risk |
Clearance margin and violations | New ComputeCollisionField |
PROPOSED |
The three ids must enter the engine overlay registry and surface through the
existing GetSupportedOverlayIds export before the dropdown presents them.
GetSupportedOverlayIds exists today (src/Nps.EngineHost/NpsAbi.cs:467–474),
but the non-planar ids do not.
Collision-critical colors come from the existing severity palette; the heatmap remains viewport content rather than a new chrome theme.
Collision finding → fix loop¶
PROPOSED — collision risk is actionable rather than decorative:
flowchart LR
C["Collision-risk critical band"] --> F["Select collision finding"]
F --> Z["Focus layer / move"]
Z --> Q{"Fix scope"}
Q -->|Global| G["Raise radius / height clearance"]
Q -->|Local| P["Paint region + override"]
G --> R["Re-slice"]
P --> R
R --> V["Replay and verify band / count"]
- Select
collision-riskin Preview or Simulate. - Click the critical marker/finding to focus its layer and move.
- Return to Prepare.
- Raise global clearance, or paint a local region and set an override.
- Re-slice; the dirty banner clears only after successful generation.
- Confirm the band downgrades and the Critical count falls.
HOW IT IS — selecting a current finding already focuses simulation state
(src/SlicerApp/MainWindow.axaml.cs:679–738; src/SimulatorApp/MainWindow.axaml.cs:665–727).
Collision fields, non-planar category, fix controls, and severity-count feedback
are PROPOSED.
Stair-step verification¶
PROPOSED — Ghost Compare verifies the visual result against a planar baseline:
- Preview the non-planar result with
nonplanar-amplitudeactive. - Turn on Ghost Compare.
- The host snapshots the active path, regenerates a baseline with
enableNonPlanar=0, and snapshots that baseline before another generation. - The baseline renders dimly beneath the non-planar path.
- Restrict the layer band and scrub curved surfaces.
- Confirm the non-planar path reduces the visible stair-step transition.
The snapshot order is mandatory because engine move pointers remain valid only
until the next load/generate/parse operation
(src/Nps.EngineHost/EngineSession.cs:392–400). Ghost Compare is visual
verification, not dimensional proof or collision certification.
Honest empty and disabled states¶
| State | Planned response |
|---|---|
| No model | Panel visible; controls disabled; Import a 3MF model to begin |
| Enable off | Detect/Paint/region edits disabled; reason shown |
| No detected/painted regions | Empty list explains how to Detect or Paint |
| Collision field unavailable | collision-risk absent from Color by, not a zero-valued fake map |
| Generated settings changed | Dirty banner + Re-slice; old visualization remains visibly stale |
See also¶
- Prepare for panel placement and the four working Process inputs.
- Preview for Color by, Ghost Compare, and layer inspection.
- Simulate for playback and findings triage.
- Slicer — interaction map for the current Enable route.
- Simulator — interaction map for current findings and overlay behavior.