Legacy Controller Settings
HardNcEnv is the model the Legacy Controller page at /controller/:tab? edits,
and this page is what that model holds: how it stands to the runner the rest of the application
configures, the three settings this screen owns alone, the ones it shares with the Controller Branch
on General Setup, and the one marker class both faces draw a work coordinate with. The screen itself
— its seven tabs, how an edit commits, its object-management chain, its viewer and its layout — is
Legacy Controller Page.
The Model It Edits, and the One It Does Not
The project carries both models side by side and serializes both. HardNcEnv is
loaded from the project's own NcEnv element unconditionally; NcRunnerSuit — the
runner plus the project's per-case dependency list — is read from its own nested element. The legacy
element is a fallback source for the suit rather than a shared store: a project file that carries
no runner element derives one from the legacy element at load time, and from then on the two drift
apart, because every later edit lands on one of them alone.
The legacy model is still read at play time. The legacy NC runner is constructed over a delegate
onto the project's NcEnv, so installing a replacement through the screen's ⋮ menu propagates
without rewiring, and a project-level switch selects which of the two pipelines plays. That switch
defaults to the SoftNc pipeline and no screen in the web application changes it; it is a scripting
property, EnableSoftNcRunner(API). The legacy
NC optimisation route is the other live reader: it is taken whenever the switch is off or the
session holds no played SoftNc layers, and it is handed MachiningProject.NcEnv directly.
What Only This Screen Edits
Three settings on this screen have no editor anywhere else in the web application — neither on the branch, nor on any other page.
Align P0, and its undo history
The Coordinate Table tab — that is the tab button's label; ISO Coordinate Table is the heading over the panel it opens — carries a third row action beside P0 and M0: Align P0, titled "Move workpiece+fixture so ProgramZero coincides with this ISO entry (mutates Fixture.GeomToTableTransformer)". It does not write the coordinate — it writes the fixture's geometry-to-table transformer, moving the workpiece and fixture so that program zero lands on the offset the row holds. The write goes to the authored setup equipment and reports the edit, so the runtime face follows at the next rebuild. The branch's Work Coordinates leaf carries P0 and M0 and no alignment.
The endpoint keeps no undo slot. It answers with the assigned translation plus the transformer as it
stood before and after the write, both serialized as XML, and the tab holds the history
itself: Undo Align and Redo Align buttons over two component-local stacks, the undo stack
capped at 32 entries and the oldest dropped past it. A third button sits beside them, Show on
Display, which belongs to the viewer rather than to the history: it is a bound toggle over the
IsoCoordinate rendering flag, carrying a visibility / visibility_off icon and writing through
the same flag endpoint the Scene dropdown writes. The two datum tabs carry the same button over
HeidenhainCoordinate. Each step posts a stashed snapshot back to a stateless revert endpoint,
which parses it and assigns the result as the fixture's transformer. Both stacks are cleared
whenever the tab's has-a-project prop changes, and the snapshot the component believes is current is
only what it last saw — a transformer changed from another surface is overwritten wholesale by the
next undo or redo rather than merged.
The engine exposes the same operation as a script call, AlignWorkpieceProgramZeroToIso(API); the history is the screen's own.
Enable Shortest Rotary Path
The Config tab's single toggle writes EnableShortestRotary, which
constructs true. Its banner reads "Shortest Rotary Path: optimises rotary axis motion to use
the shortest angular distance between positions." On the legacy pipeline the flag gates one step:
each rotary axis of a block is cycled into the ±180° window around the previous block's value. The
toggle is narrower than it reads, because that same cycle is applied unconditionally on
Heidenhain — the brand branch runs it before the flag is consulted, so
clearing the box changes nothing there.
The runner's dependency layer declares no counterpart: no brand parameter table, no generic config
and no branch leaf carries a shortest-rotary switch. The nearest thing the runner pipeline has is the
Heidenhain M126 / M127 pair, which is read from the program text rather than from any setting.
Heidenhain master-axis character
The Brand tab grows a second card while the brand is Heidenhain, holding one select over A,
B, C labelled Master-axis character. It writes
HeidenhainMasterAxisChar, a character face over the integer axis
direction the PLANE … SEQ solution family is resolved against. Reads are normalised: anything that
is not B or C after trimming and upper-casing becomes A. On the runner pipeline the master
rotary is derived rather than configured — it is the first declared rotary axis — so the branch
has nothing to expose and no leaf for it.
What It Shares With the Branch
Naming what is not exclusive matters as much. The CNC brand, the stroke limits, the rapid feed, the tool-change time, the tool offset table with its tool-house dependence, the work coordinates with their P0 and M0 actions, and the Heidenhain datum preset and datum shift tables all have editors on the branch — see Brand Matrix for which of those leaves each brand grows. The Max Speed (rpm) column has a counterpart too: on the runner pipeline the rotary speed ceiling is read from the rapid-feedrate config, and the legacy import funnels this field into it at rpm × 360 deg/min, so the branch's Rapid Feedrates leaf edits the runner-side number.
One control on this screen writes a value the branch also writes. Set ideal offset dependent on tool house is a project-level configuration flag rather than a member of either NC model, and both the Offset Table tab and the branch's Tool Offsets leaf read and write that one flag. The two tables stay separate: this tab's Refresh from Tool House recomputes MillingToolOffsetTable from MachiningToolHouse, while the branch's refresh recomputes the runner's own tool-offset table.
Two Faces of a Work Coordinate
The work-coordinate marker is one displayee class serving two providers. The screen's viewer draws
it from IsoCoordinateTable — a
IsoCoordinateTable instance owned by the legacy model, which
constructs with G54 … G59 and G59.1 … G59.9 all at zero. The General Setup canvas builds the
same displayee over the active runner's effective
IIsoCoordinateConfig instead, which on most brands is the brand
parameter table. Same marker, same code, two stores.
Selecting a row on the ISO Coordinate Table tab writes the marker's id onto the shared Execution displayee, so it decides which offset the marker draws at. It decides that whether or not the marker is drawn: all three coordinate flags are off in the shipped rendering-flag set — as are the machine tool and the cutter, leaving the workpiece, the fixture, the dimension bar and the cutter-location strip as the four that arrive on — so on an untouched project the selection column moves something invisible until Show on Display is pressed. The datum tabs also carry a single-selection column, but nothing is sent when it changes — there the selection is a highlight and nothing more.
Source Code Path
See HiNC App Anatomy for git repository links.
Web Application
HiNC-2025-webservice (Quasar CLI SPA):
wwwroot-src/src/components/controller/CoordinateTableTab.vue— Align P0 with its two client-side history stacks and their cap, and the Show on Display toggle bound to theIsoCoordinaterendering flag.wwwroot-src/src/components/controller/DatumPresetTab.vueandwwwroot-src/src/components/controller/DatumShiftTab.vue— the same Show on Display button overHeidenhainCoordinate, and the row selection that is a highlight and nothing more.wwwroot-src/src/components/controller/OffsetTableTab.vue— Refresh from Tool House, and the two-step toggle over the project-level tool-house dependence flag the branch also writes.wwwroot-src/src/components/controller/ConfigTab.vue— the shortest-rotary toggle and its banner.wwwroot-src/src/components/controller/BrandTab.vue— the Heidenhain master-axis card: its read normalisation and its write.wwwroot-src/src/api/renderingFlags.ts— the flag indices those toggles write, and which of the shipped set default on.wwwroot-src/src/api/controller.ts— the typed wrappers over the align and revert endpoints, and the brand constants these settings are read against.Controller/ControllerController.cs— the align endpoint that snapshots the transformer either side of the write, and the stateless revert this screen's history posts back to.
HiAPI Engine
HiUniNc/Numerical/HardNcEnv.cs— the model this screen edits: the coordinate, datum and offset tables, the stroke boxes that construct infinite, the rapid rate and tooling time, the shortest-rotary flag with its Heidenhain exclusion, and the master-axis character over its integer direction.HiUniNc/Numerical/HardNcLine.cs— the legacy consumers of two of those settings: the shortest-rotary path application and theSEQsolve that reads the master-axis direction.HiUniNc/Numerical/MillingToolOffsetTable.cs— the offset table and the tool-house recompute the Refresh button calls.HiMech/NcParsers/Dependencys/Generic/IsoCoordinateTable.cs— the coordinate table type and the fifteen G-code keys it constructs with, shared by name with the runner's brand-agnostic table.HiMech/Machining/MachiningEquipmentUtils/MachiningEquipmentUtil.cs— the alignment itself: the translation written into the fixture's geometry-to-table transformer.HiMech/NcParsers/SoftNcRunner.cs— the legacy import: which legacy fields are funnelled into which runner dependency, including the rotary speed conversion into the rapid-feedrate config.HiMech/NcParsers/LogicSyntaxs/PolarInterpolationUtil.cs— the rotary speed ceiling the runner pipeline reads, and why it is the rapid-rate bucket rather than a setting of its own.HiMech/NcParsers/LogicSyntaxs/Heidenhain/HeidenhainPlaneTiltSyntax.cs— the derived master rotary on the runner pipeline: the first declared rotary axis, with no configured alternative.HiNc/MachiningProcs/MachiningProject.cs— where both models hang off the project, and the load path that derives a runner from the legacy element only when no runner element is present.HiNc/MachiningProcs/LocalProjectService.cs— the legacy runner built over a delegate onto the project's model, and the switch that selects which pipeline is active.HiNc/Numerical/FilePlayers/HardNcRunner.cs— the legacy runner itself.HiNc/MachiningProcs/SessionShell.cs— the scripting face of the pipeline switch and of the alignment, and the optimisation route that passes the legacy model directly.
See Also
- Legacy Controller Page — the screen these settings are edited on: its seven tabs, its commit and rollback rules, its object-management chain and its viewer
- Controller Branch — the SoftNcRunner-native controller branch that carries the editors for everything named above as shared
- General Setup Page — the page that hosts that branch, and the rest of the equipment tree beside it