Table of Contents

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 the IsoCoordinate rendering flag.
  • wwwroot-src/src/components/controller/DatumPresetTab.vue and wwwroot-src/src/components/controller/DatumShiftTab.vue — the same Show on Display button over HeidenhainCoordinate, 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 the SEQ solve 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