deploy webservice static-file routing for docsite folder URLs, per-instance step-cache db, and constant-height panel title bars.

This commit is contained in:
2026-08-27 14:51:37 +08:00
parent 1fc510af5e
commit 2a98ae7556
1468 changed files with 182837 additions and 18888 deletions
@@ -94,19 +94,490 @@
<h3 id="classes">
Classes
</h3>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainCannedCycleSyntax.html">HeidenhainCannedCycleSyntax</a></dt>
<dd><p>Bridges the klartext machining-cycle vocabulary onto the shared ISO
canned-cycle machinery. Owns the self-carrying
<a class="xref" href="Hi.NcParsers.Keywords.Heidenhain.MachiningCycleDef.html">MachiningCycleDef</a> store (single-step lookback + rewrite
on every block — the P1 datum-shift pattern) and the call-once vs
modal split:</p>
<ul><li><b>Definition</b> (<code>Parsing.MachiningCycle</code> from
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Heidenhain.CyclDefSyntaxs.HeidenhainMachiningCycleSyntax.html">HeidenhainMachiningCycleSyntax</a>): mapped to ISO slots at
definition time — 200 → G81/G82/G83 (peck when Q202 &lt; |Q201|),
232 → G81 (start point Q225/Q226/Q227, end Q386, feed Q207),
251/252/253 → G81/G83 (surface Q203, clearance Q200, depth Q201,
plunge feed Q206, step-down Q202). A definition never executes by
itself. Unsupported numbers (19, …) are recognized-but-not-simulated:
consumed whole with <code>HeidenhainCycl--Unsupported</code>, stored
unarmable so a later call warns instead of moving. Required
parameters that are missing or non-literal make the store unarmable
with <code>HeidenhainCycl--ParamsNotLiteral</code>.</li><li><b>Call-once</b> (<code>CYCL CALL [POS]</code> record from
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Heidenhain.HeidenhainCyclCallSyntax.html">HeidenhainCyclCallSyntax</a>, or an <code>M99</code> flag on a
positioning block — the TNC block-wise call, unrelated to the Fanuc
return M99): writes the mapped cycle as a direct <code>Parsing.G8x</code>
sub-section on this block, which
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.CannedCycleResolveSyntax.html">CannedCycleResolveSyntax</a> resolves and the shared cycle
syntaxes expand into a <a class="xref" href="Hi.NcParsers.Keywords.CompoundMotion.html">CompoundMotion</a>. POS coordinates
override the stored X/Y; the POS Z is a pre-position, recorded but
never fed into the hole-bottom slot. The ISO modal-lookback branch is
deliberately bypassed: it has no positioning gate, so an armed
<a class="xref" href="Hi.NcParsers.Keywords.CannedCycle.html">CannedCycle</a> would re-execute on flag-only blocks —
wrong for klartext.</li><li><b>Modal</b> (<code>M89</code>): sets <a class="xref" href="Hi.NcParsers.Keywords.Heidenhain.MachiningCycleDef.html#Hi_NcParsers_Keywords_Heidenhain_MachiningCycleDef_Modal">Modal</a>;
each subsequent block carrying root axis words (and no
<code>CArc</code> statement) fires the same direct-section path with the
block's X/Y consumed into the cycle. <code>M99</code> fires once and
clears the modality; a new <code>CYCL DEF</code> replaces the store.</li><li><b>Seal</b>: on every non-firing block whose previous block
carries an active <a class="xref" href="Hi.NcParsers.Keywords.CannedCycle.html">CannedCycle</a> term, a <code>G80</code> flag
is injected (the P0 G00/G01 injection pattern) so
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.CannedCycleResolveSyntax.html">CannedCycleResolveSyntax</a> writes the cancel sentinel —
the one-shot execution never leaks into ISO modal repetition.</li></ul>
<p>
Known divergences (recorded, corpus-benign): the cycle's mapped feed
enters the modal <a class="xref" href="Hi.NcParsers.Keywords.Feedrate.html">Feedrate</a> section during expansion (ISO
semantics; the Siemens MCALL precedent accepts the same leak); the
final retract plane is the ISO G98 initial level, not Q204's second
set-up clearance (Q204 is recorded in the definition store only).
</p>
Must run after the tilt/RTCP family and immediately before
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.CannedCycleResolveSyntax.html">CannedCycleResolveSyntax</a>.
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainCircleCenterSyntax.html">HeidenhainCircleCenterSyntax</a></dt>
<dd><p>Heidenhain-specific: turns the <code>Parsing.CC</code> record into the
modal <code>HeidenhainCircleCenter { X, Y, Z? }</code> section (absolute
program coordinates). Self-carrying every block (PlaneSelect pattern
— detected ?? previous), so the arc syntax's single-step read always
works without ModalCarry involvement; a CC with partial axes merges
the missing components from the previous center. Must run before
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainCircularMotionSyntax.html">HeidenhainCircularMotionSyntax</a>.</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainCircularMotionSyntax.html">HeidenhainCircularMotionSyntax</a></dt>
<dd><p>Heidenhain circular motion — the Klartext half of the brand's two
arc syntaxes. The shared <a class="xref" href="Hi.NcParsers.LogicSyntaxs.CircularMotionSyntax.html">CircularMotionSyntax</a> (with
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.CircularMotionSyntax.html#Hi_NcParsers_LogicSyntaxs_CircularMotionSyntax_IsIjkAbsolute">IsIjkAbsolute</a> set) runs right
after it for the DIN/ISO dialect: the two gates are per-block
exclusive (a klartext arc has <code>CArc</code> and no I/J/K/R; an ISO arc
the reverse) and both honor the single Group 01
<a class="xref" href="Hi.NcParsers.Keywords.MotionEvent.html">MotionEvent</a> slot.
Gated by the <code>Parsing.C</code> statement marker (klartext arcs
carry no G02/G03 and no modal arc continuation): the endpoint comes
from the block's resolved <code>ProgramXyz</code>, the center from the
modal <a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainCircleCenterSyntax.html">HeidenhainCircleCenterSyntax</a> section (implicit
center = current position when no CC was ever given), and the
direction from <code>DR-</code> (CW → G02) / <code>DR+</code> (CCW → G03). A
closed arc on the active plane is a full circle. A missing DR warns
(<code>Arc-DR&ndash;Missing</code>) and degrades to the modal linear move to the
endpoint (chord).</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainCoordinateOffsetSyntax.html">HeidenhainCoordinateOffsetSyntax</a></dt>
<dd><p>Heidenhain-specific: resolves coordinate offset from
CYCL DEF 247 (Datum Preset) and CYCL DEF 7 (Datum Shift).</p>
<p>
CYCL DEF 247 Q339=N: selects datum preset table entry N.
CYCL DEF 7 #N: selects datum shift table entry N.
CYCL DEF 7 X/Y/Z: applies direct XYZ shift values.
CYCL DEF 247 Q339=N: selects datum preset table entry N — written to
the shared <a class="xref" href="Hi.NcParsers.Keywords.CoordinateOffset.html">CoordinateOffset</a> section (kept alive
modally by <a class="xref" href="Hi.NcParsers.LogicSyntaxs.IsoCoordinateOffsetSyntax.html">IsoCoordinateOffsetSyntax</a> via
<a class="xref" href="Hi.NcParsers.Dependencys.HeidenhainDatumTable.html">HeidenhainDatumTable</a> synthetic-id resolution).
</p>
<p>
CYCL DEF 7 (<code>#N</code> table row or direct X/Y/Z) is <b>additive on top
of the active preset</b> (TNC semantics; HardNc oracle composes
<code>-preset + shift</code>): it is written to its own <code>DatumShift</code>
section with a separate <code>ProgramToMcTransform</code> entry
(<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainCoordinateOffsetSyntax.html#Hi_NcParsers_LogicSyntaxs_Heidenhain_HeidenhainCoordinateOffsetSyntax_DatumShiftTransformSource">DatumShiftTransformSource</a>) so preset and shift compose
in the transform chain instead of replacing each other. The shift is
carried modally by this syntax itself: on blocks without a CYCL DEF,
a numbered row re-resolves from the table and a direct shift carries
its values forward. Cancelling is a zero shift
(<code>CYCL DEF 7.1 X+0 Y+0 Z+0</code>).
</p>
For DIN/ISO compatibility (G54–G59), use <a class="xref" href="Hi.NcParsers.LogicSyntaxs.IsoCoordinateOffsetSyntax.html">IsoCoordinateOffsetSyntax</a>
in addition to this syntax in the Heidenhain syntax list.
Uses replace-by-source (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.CoordinateOffsetUtil.html#Hi_NcParsers_LogicSyntaxs_CoordinateOffsetUtil_TransformSource">TransformSource</a>)
so both syntaxes can coexist without double-composing.
Uses replace-by-source so both syntaxes coexist without double-composing.
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainCyclePrePositionSyntax.html">HeidenhainCyclePrePositionSyntax</a></dt>
<dd><p>Lifts the expanded cycle's initial plane to the recorded TNC
pre-position Z. A <code>CYCL CALL POS … Z±n</code> (and an M99/M89
positioning block's own Z word) positions the spindle BEFORE the cycle
runs; the shared ISO expansion instead anchors its initial plane — the
first rapid and the G98 final retract — on the PREVIOUS block's Z.
Left unlifted, a call that climbs to a safe Z before drilling would be
simulated traversing at the stale old Z (phantom collisions through
fixtures) and G98 would plunge the tool back to that stale Z after the
hole.</p>
<p>
Mechanics: when the <a class="xref" href="Hi.NcParsers.Keywords.Heidenhain.HeidenhainCyclCall.html">HeidenhainCyclCall</a> record carries a
numeric <code>Z</code> and a <a class="xref" href="Hi.NcParsers.Keywords.CompoundMotion.html">CompoundMotion</a> was expanded, the
first item (the initial-plane rapid — both shared cycle syntaxes emit
it first) and, under G98, the final item and the block's final
<code>ProgramXyz</code> are re-anchored to the pre-position Z. G99 finals
(R-plane) are untouched. Runs after the shared cycle syntaxes and
before <a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainCycleRetractSyntax.html">HeidenhainCycleRetractSyntax</a> (whose appended M140
retract builds on the lifted final point).
</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainCycleRetractSyntax.html">HeidenhainCycleRetractSyntax</a></dt>
<dd><p>Consumes the <code>Parsing.M140</code> record that
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainMFunctionSyntax.html">HeidenhainMFunctionSyntax</a> deferred on a may-fire-cycle
block — a <code>CYCL CALL [POS]</code> host (<code>… M140 MB+n</code> is a real
house.H shape), an <code>M99</code>/<code>M89</code> flag block, or any block
under armed M89 modality.
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.text.json.nodes.jsonobject">WriteCompoundMotion(JsonObject, string, JsonArray, Vec3d)</a> destroys any
pre-written <a class="xref" href="Hi.NcParsers.Keywords.MotionEvent.html">MotionEvent</a>, so the retract is appended
<b>after</b> the cycle expansion instead:</p>
<ul><li>Cycle expanded — a rapid item to (final X, final Y, retract Z)
is appended to the <a class="xref" href="Hi.NcParsers.Keywords.CompoundMotion.html">CompoundMotion</a> items and the block's
final <code>ProgramXyz</code> is lifted to the retract plane. The MB math is
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.text.json.nodes.jsonobject">ResolveRetractTargetZ(JsonObject, Vec3d, List&lt;INcDependency&gt;, ISentenceCarrier, NcDiagnosticProgress)</a> verbatim.
The real TNC runs M140 at block start (retract, then position + cycle);
appending it is a transient-only divergence — the endpoint chain
re-anchors on the next command point (the P3 PLANE MOVE precedent) and
the appended order is the safer trajectory. An <code>F</code> on the M140 is
recorded on the item but the appended retract stays rapid
(corpus M140-on-call blocks are all F-less).</li><li>Cycle did not expand (call consumed without motion) — the plain
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainMFunctionSyntax.html">HeidenhainMFunctionSyntax</a> retract behavior runs here
unchanged, so a fail-soft call never silently drops the retract.</li></ul>
Must run after the shared cycle syntaxes
(<a class="xref" href="Hi.NcParsers.LogicSyntaxs.DrillingCycleSyntax.html">DrillingCycleSyntax</a>/<a class="xref" href="Hi.NcParsers.LogicSyntaxs.PeckDrillingCycleSyntax.html">PeckDrillingCycleSyntax</a>)
and before <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McXyzSyntax.html">McXyzSyntax</a>.
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainMFunctionSyntax.html">HeidenhainMFunctionSyntax</a></dt>
<dd><p>Heidenhain-specific M-function semantics for the near-universal corpus
family:</p>
<ul><li><code>M126</code>/<code>M127</code> — shortest-path rotary traverse on/off.
Writes the modal <code>RotaryWrap { Shortest }</code> section consumed by
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcCyclicPathSyntax.html">McAbcCyclicPathSyntax</a> (absent = shortest, the shared
default); the Heidenhain preset's Logic ModalCarry tracks the
section.</li><li><code>M128</code>/<code>M129</code> — owned by <a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainRtcpSyntax.html">HeidenhainRtcpSyntax</a>
since P3 (full RTCP on the <code>ToolHeightCompensation</code> section);
this syntax no longer touches them.</li><li><code>M140 MB</code> — tool-axis retract. Executes a machine-coordinate
move along +Z (the corpus machines are table-tilting, so the tool
axis stays machine +Z; a head-machine generalization is a recorded
P6 backlog item):
<code>MB+n</code> retracts by n mm, <code>MB MAX</code> retracts to the positive
Z stroke limit (<a class="xref" href="Hi.NcParsers.Dependencys.IStrokeLimitConfig.html">IStrokeLimitConfig</a>; unresolvable limit
warns <code>M140--NoStrokeLimit</code> and skips). The retract runs at the
modal feed (the statement's F is recorded on the MotionEvent as
<code>RetractFeedrate</code>, not folded into the modal feedrate).</li></ul>
Must run before <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcCyclicPathSyntax.html">McAbcCyclicPathSyntax</a> (RotaryWrap) and
before <a class="xref" href="Hi.NcParsers.LogicSyntaxs.LinearMotionSyntax.html">LinearMotionSyntax</a>/<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McXyzSyntax.html">McXyzSyntax</a>
(M140 occupies the block's MotionEvent).
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainMirrorTransformSyntax.html">HeidenhainMirrorTransformSyntax</a></dt>
<dd><p>Simulates the Heidenhain DIN/ISO <code>G28</code> MIRROR IMAGE function
(the CYCL DEF 8 twin): consumes the statement list
<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Heidenhain.HeidenhainMirrorImageSyntax.html">HeidenhainMirrorImageSyntax</a> recorded under
<code>Parsing.MirrorImage</code>, keeps the modal mirror set in the root
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainMirrorTransformSyntax.html#Hi_NcParsers_LogicSyntaxs_Heidenhain_HeidenhainMirrorTransformSyntax_SectionKey">SectionKey</a> section (each statement REPLACES the set —
course 62192's four-quadrant idiom relies on <code>G28 Y</code> after
<code>G28 X Y</code> leaving only Y mirrored; bare <code>G28</code> resets), and
writes the sign-flip matrix into
<a class="xref" href="Hi.NcParsers.Keywords.ITransformationDef.html#Hi_NcParsers_Keywords_ITransformationDef_ProgramToMcTransform">ProgramToMcTransform</a> as the
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainMirrorTransformSyntax.html#Hi_NcParsers_LogicSyntaxs_Heidenhain_HeidenhainMirrorTransformSyntax_TransformSource">TransformSource</a> entry.</p>
<p>
Must run <b>before</b> every other transform writer
(<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainPlaneTiltSyntax.html">HeidenhainPlaneTiltSyntax</a> downward) so the mirror
entry is the chain's <b>first</b> — the mirror flips program
coordinates about the current datum inside the active working plane,
i.e. innermost: tilt, tool-height and coordinate-offset entries
compose after it and are never themselves mirrored. Because every
motion semantic resolves contours in program coordinates and maps
each interpolated point through the composed chain
(<a class="xref" href="Hi.NcParsers.Syntaxs.SyntaxPiece.html">CreateProgramPosToMcFunc(LazyLinkedListNode&lt;SyntaxPiece&gt;, IMachineAxisConfig)</a>),
the arc-handedness flip (G02↔G03) and the radius-compensation side
flip (G41↔G42) a real control performs under a single-axis mirror
emerge from the pointwise mapping — no re-tagging of
<a class="xref" href="Hi.NcParsers.Keywords.IArcMotionDef.html#Hi_NcParsers_Keywords_IArcMotionDef_IsCcw">IsCcw</a> or the compensation side happens,
and none is needed.
</p>
<p>
Two statement shapes stay recognized-but-not-simulated:
a rotary axis letter (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainMirrorTransformSyntax.html#Hi_NcParsers_LogicSyntaxs_Heidenhain_HeidenhainMirrorTransformSyntax_RotaryUnsupportedId">RotaryUnsupportedId</a> — a rotary
mirror is not representable in the XYZ transform chain; the letter is
dropped from the set, the statement still replaces) and the
Fanuc-shaped valued form (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainMirrorTransformSyntax.html#Hi_NcParsers_LogicSyntaxs_Heidenhain_HeidenhainMirrorTransformSyntax_ValuedUnsupportedId">ValuedUnsupportedId</a> — the
manual's mirror idiom is bare letters, so <code>G91 G28 X0 Y0 Z0</code> in
a mislabeled <code>.I</code> file must not arm a full-XYZ mirror; the
statement is consumed with zero effect).
</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainMotionModeSyntax.html">HeidenhainMotionModeSyntax</a></dt>
<dd><p>Heidenhain-specific: maps the klartext <code>L</code> statement marker
(written by <a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Heidenhain.HeidenhainLSyntax.html">HeidenhainLSyntax</a>) onto the shared ISO
motion-mode vocabulary. An <code>L</code> block carrying the one-shot
<code>FMAX</code> flag becomes a rapid (G00) block; every other <code>L</code>
block is a feed move (G01) driven by the modal feedrate. The injected
G00/G01 flag is consumed downstream exactly like a DIN/ISO block —
by <a class="xref" href="Hi.NcParsers.LogicSyntaxs.LinearMotionSyntax.html">LinearMotionSyntax</a> on ordinary moves and by
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.MachineCoordSelectSyntax.html">MachineCoordSelectSyntax</a> on machine-coordinate (M91)
moves — so no shared syntax needs Heidenhain-specific behavior.</p>
<p>
FMAX is one-shot on the real TNC: because every klartext motion is an
<code>L</code> statement and this syntax stamps a mode per statement, the
rapid mode never leaks into the next block — the following <code>L</code>
without FMAX is stamped G01 again. <code>FAUTO</code> (feed from cycle) is
consumed as a feed move. Must be placed at the top of the Logic bundle,
before <a class="xref" href="Hi.NcParsers.LogicSyntaxs.MachineCoordSelectSyntax.html">MachineCoordSelectSyntax</a> and
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.LinearMotionSyntax.html">LinearMotionSyntax</a>.
</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainPathSmoothingSyntax.html">HeidenhainPathSmoothingSyntax</a></dt>
<dd><p>Heidenhain-specific: consumes the structured CYCL DEF 32 TOLERANCE
record (<a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Heidenhain.CyclDefSyntaxs.HeidenhainToleranceCyclSyntax.html">HeidenhainToleranceCyclSyntax</a>) into the shared
modal <code>PathSmoothing</code> section (tracked by the Logic ModalCarry):
a positive tolerance arms smoothing
(<code>{IsEnabled:true, Term:&ldquo;CYCL DEF 32&rdquo;, Tolerance, HscMode?, Ta?}</code>);
a bare or zero-tolerance cycle cancels it. Untouched blocks are left
to ModalCarry; the stream's first block seeds a conservative
<code>{IsEnabled:false}</code> (Siemens sibling shape). Replaces the dead
<code>FanucPathSmoothingSyntax</code> in the Heidenhain list (it read
<code>Parsing[&ldquo;G05.1&rdquo;]</code>, which no Heidenhain capture produces).</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainPivotTransformationSyntax.html">HeidenhainPivotTransformationSyntax</a></dt>
<dd><p>Heidenhain pivot gate over the shared engine
(<a class="xref" href="Hi.NcParsers.LogicSyntaxs.PivotTransformUtil.html">PivotTransformUtil</a>): writes the
<a class="xref" href="Hi.NcParsers.Syntaxs.TransformationUtil.html#Hi_NcParsers_Syntaxs_TransformationUtil_PivotTransformSource">PivotTransformSource</a> entry on blocks
where commanded XYZ needs the Pn→MC kinematic rigid transform — an
active tilted plane (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainPlaneTiltSyntax.html">HeidenhainPlaneTiltSyntax</a>'s
<code>PLANE SPATIAL</code> term, or a mixed-dialect G68/G68.2 term), an
active RTCP modal (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainRtcpSyntax.html#Hi_NcParsers_LogicSyntaxs_Heidenhain_HeidenhainRtcpSyntax_RtcpTerms">RtcpTerms</a> on
the <a class="xref" href="Hi.NcParsers.Keywords.ToolHeightCompensation.html">ToolHeightCompensation</a> section — the term check
covers RTCP blocks whose rotary state is stable, which the
Dynamic-entry branch alone would miss), or a Dynamic chain entry.</p>
<p>
The third sibling gate after <a class="xref" href="Hi.NcParsers.LogicSyntaxs.PivotTransformationSyntax.html">PivotTransformationSyntax</a>
(ISO/Fanuc) and <a class="xref" href="Hi.NcParsers.LogicSyntaxs.Siemens.SiemensPivotTransformationSyntax.html">SiemensPivotTransformationSyntax</a>;
all write the identical JSON vocabulary through the shared engine and
only one gate is registered per brand pipeline. Heidenhain has no
plain-geometry-frame exclusion (klartext datum shifts use their own
chain sources, never <a class="xref" href="Hi.NcParsers.Keywords.TiltTransform.html">TiltTransform</a>). Same
chain-position contract: after all Pn-frame writers, so the
<code>PivotTransform</code> entry lands last.
</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainPlaneTiltSyntax.html">HeidenhainPlaneTiltSyntax</a></dt>
<dd><p>Heidenhain PLANE consumer — the Heidenhain sibling of
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.IsoG68p2TiltSyntax.html">IsoG68p2TiltSyntax</a> (Fanuc G68.2) and
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Siemens.SiemensCycle800TiltSyntax.html">SiemensCycle800TiltSyntax</a> both XmlDocs promise.</p>
<ul><li><b>PLANE SPATIAL</b> — composes the tilted work plane
<code>Rx(SPA)·Ry(SPB)·Rz(SPC)</code> (row-vector, degrees; the HardNc
oracle's <code>HeidenhainPlaneSpatialArg</code> matrix verbatim) into
<a class="xref" href="Hi.NcParsers.Keywords.ITransformationDef.html#Hi_NcParsers_Keywords_ITransformationDef_ProgramToMcTransform">ProgramToMcTransform</a> as the shared
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.TiltTransformUtil.html#Hi_NcParsers_LogicSyntaxs_TiltTransformUtil_TransformSource">TransformSource</a> entry with
<code>Term = "PLANE SPATIAL"</code>.</li><li><b>MOVE / TURN</b> — the implicit rotary positioning (the
CYCLE800 "G53.1 half"): with <a class="xref" href="Hi.Numerical.Xyzabc.IMachineKinematics.html">IMachineKinematics</a> wired
the plane orientation is solved to machine ABC (full-orientation IK
first so a pure in-plane <code>SPC</code> under TABLE ROT still turns the
table; tool-axis-normal fallback for machines with fewer rotary DOF;
no identity short-circuit — the explicit zero-angle
<code>PLANE SPATIAL SPA+0 SPB+0 SPC+0 TURN</code> is the klartext idiom
for returning the rotaries to 0, oracle parity)
and written into <a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateStateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateStateDef_MachineCoordinateState">MachineCoordinateState</a>
plus a non-modal <a class="xref" href="Hi.NcParsers.Keywords.MotionEvent.html">MotionEvent</a> with
<code>Term = "PLANE SPATIAL"</code>. MOVE's <code>DIST</code> (tool retract
radius during the swivel) and the TCP-preserving XYZ compensation
are recorded but not simulated — the machine XYZ stays at the
previous position like TURN, a transient-only divergence from the
HardNc oracle (endpoints re-anchor at the next commanded point);
MOVE's <code>F</code> is recorded on the event as <code>MoveFeedrate</code>.</li><li><b>COORD ROT</b> is honored only when the plane rotates purely
about the tool axis (<a class="xref" href="Hi.NcParsers.Dependencys.Heidenhain.HeidenhainParameterTable.html#Hi_NcParsers_Dependencys_Heidenhain_HeidenhainParameterTable_ToolAxisDirection">ToolAxisDirection</a>,
TNC manual rule; HardNc parity): the coordinate system rotates and
the rotaries stay. Any other rotation — or TABLE ROT, or neither
word — positions the rotary axes on MOVE/TURN.</li><li><b>SEQ±</b> is recorded in the section; when the IK solution's
master rotary (first declared rotary axis) violates an explicit SEQ
preference the preference is not applied and
<code>Coord-Tilt--007</code> warns (solution-family selection is not
modeled; the HardNc ±2π window wrap would be undone by
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcCyclicPathSyntax.html">McAbcCyclicPathSyntax</a>'s shortest-cyclic tail pass, and
the corpus never exercises SEQ with MOVE/TURN).</li><li><b>PLANE RESET</b> — the shared inactive sentinel
(<code>Term = "G69"</code> + identity entry). The rotary axes are not
re-positioned on reset (CYCLE800 cancel precedent; corpus programs
follow with explicit rotary moves).</li><li><b>PLANE VECTOR / PROJECTED / EULER / POINTS / RELATIV /
AXIAL</b> — recognized-but-not-simulated: consumed,
<code>HeidenhainPlane--Unsupported</code> warns, and the previous tilt
state carries unchanged (the HardNc oracle instead reuses a stale
spatial arg here — SoftNc deliberately exceeds it).</li></ul>
<p>
Owns the once-per-block <a class="xref" href="Hi.NcParsers.Keywords.TiltTransform.html">TiltTransform</a> modal carry for
the Heidenhain list (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.TiltTransformUtil.html#Hi_NcParsers_LogicSyntaxs_TiltTransformUtil_CarryForwardFromPrevious_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__System_Text_Json_Nodes_JsonObject_">CarryForwardFromPrevious(LazyLinkedListNode&lt;SyntaxPiece&gt;, JsonObject)</a>).
Must run <b>before</b> <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ToolHeightOffsetSyntax.html">ToolHeightOffsetSyntax</a> /
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainToolOffsetSyntax.html">HeidenhainToolOffsetSyntax</a> (their translation follows
the tilt entry's normal — the oracle's tool-normal-tiltable rule)
and before <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a> / the coordinate-offset
syntaxes (chain order: tilt entry ahead of <code>CoordinateOffset</code>,
mirroring the Siemens frame slot; implicit MC rotary values must
land before McAbc's per-axis lookback).
</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainProgramHeaderSyntax.html">HeidenhainProgramHeaderSyntax</a></dt>
<dd><p>Heidenhain-specific: consumes the <code>Parsing.PGM</code> record
(<code>BEGIN|END PGM name MM|INCH</code>) — the unit word is pushed into
<code>Parsing.Flags</code> for the <a class="xref" href="Hi.NcParsers.LogicSyntaxs.UnitModeSyntax.html">UnitModeSyntax</a> instance
configured with <code>InchCodes=[&ldquo;INCH&rdquo;], MetricCodes=[&ldquo;MM&rdquo;]</code> (which
must run after this syntax), and <code>END PGM</code> writes the shared
one-shot <code>ProgramEnd</code> section (existence-checked by its
consumers exactly like M30). Consuming PGM also removes the
program-header unconsumed noise every klartext file used to emit.</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainRadiusCompSyntax.html">HeidenhainRadiusCompSyntax</a></dt>
<dd><p>Heidenhain-specific: maps the klartext radius-compensation words
captured by <a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Heidenhain.HeidenhainLSyntax.html">HeidenhainLSyntax</a> (<code>RL</code>/<code>RR</code>/<code>R0</code>
boolean Parsing-root records) onto the shared vocabulary consumed by
the radius-compensation pass: <code>RL → Parsing.G41 {D: toolId}</code>,
<code>RR → G42</code>, <code>R0 → G40</code> flag. The offset id is the current
tool number (klartext has no D word; <code>IToolOffsetConfig</code> documents
the offset id as the Heidenhain tool number), resolved by walking back
to the most recent <code>ToolChange</code> section. A missing or non-numeric
tool id degrades to mode-only injection (radius 0 — the compensation
pass records the state but applies no geometric offset) with an
<code>RadiusComp&ndash;ToolUnresolved</code> warning.</p>
<p>
Must run before the PostLogic radius-compensation pass (any Logic
position works — PostLogic sees completed Logic output) and after
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainToolChangeSyntax.html">HeidenhainToolChangeSyntax</a> so a same-block TOOL CALL is
visible.
</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainRtcpSyntax.html">HeidenhainRtcpSyntax</a></dt>
<dd><p>Heidenhain RTCP (M128/M129, FUNCTION TCPM/FUNCTION RESET TCPM): the
Heidenhain sibling of <a class="xref" href="Hi.NcParsers.LogicSyntaxs.G43p4RtcpSyntax.html">G43p4RtcpSyntax</a> and
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Siemens.SiemensTraoriSyntax.html">SiemensTraoriSyntax</a>. While RTCP is active the
<a class="xref" href="Hi.NcParsers.Keywords.IToolHeightCompensationDef.html">IToolHeightCompensationDef</a> section carries the
activating term (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainRtcpSyntax.html#Hi_NcParsers_LogicSyntaxs_Heidenhain_HeidenhainRtcpSyntax_M128Term">M128Term</a> or <a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainRtcpSyntax.html#Hi_NcParsers_LogicSyntaxs_Heidenhain_HeidenhainRtcpSyntax_TcpmTerm">TcpmTerm</a>)
and the <code>ToolHeightCompensation</code> chain entry becomes a
tool-normal · offset translation at the block endpoint ABC
(<a class="xref" href="Hi.NcParsers.Syntaxs.TransformationUtil.html#Hi_NcParsers_Syntaxs_TransformationUtil_MakeToolHeightMat_Hi_Numerical_Xyzabc_IMachineKinematics_Hi_Geom_Vec3d_System_Double_">MakeToolHeightMat(IMachineKinematics, Vec3d, double)</a>), tagged
<a class="xref" href="Hi.NcParsers.Syntaxs.TransformationUtil.html#Hi_NcParsers_Syntaxs_TransformationUtil_KindDynamic">KindDynamic</a> when the rotary state
changes across the block — the signal that routes the block to
<a class="xref" href="Hi.NcParsers.Keywords.Generic.MotionForm.html#Hi_NcParsers_Keywords_Generic_MotionForm_ClLinear">ClLinear</a> per-step IK.</p>
<p>
Tool length ownership stays with the TOOL CALL machinery
(<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainToolOffsetSyntax.html">HeidenhainToolOffsetSyntax</a> — table height + DL, which
runs earlier in the bundle): activation adopts the compensation
already resolved on this or the previous block and records the
adopted owner in <a class="xref" href="Hi.NcParsers.LogicSyntaxs.Siemens.SiemensTraoriSyntax.html#Hi_NcParsers_LogicSyntaxs_Siemens_SiemensTraoriSyntax_PriorTermKey">PriorTermKey</a>;
a TOOL CALL during the modal re-takes the section with the fresh
offset; M129 / FUNCTION RESET TCPM hands the section back to the
recorded owner (default <a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainToolChangeSyntax.html#Hi_NcParsers_LogicSyntaxs_Heidenhain_HeidenhainToolChangeSyntax_Term">Term</a> —
klartext tool-length compensation survives RTCP deactivation). The
TOOL CALL <code>Delta_mm</code> (DL) rides along so the hand-back restores
it. A deactivation with no active RTCP (the corpus' ubiquitous
program-head <code>M129</code>) is consumed silently. Same-block
contradiction (M128 with M129): the off state wins conservatively
(the P1 rule, kept for continuity).
</p>
<p>
The M128 feed limit (<code>M128 F6000.</code>, or an FQn token the
evaluator could not resolve) is recorded on the section as
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainRtcpSyntax.html#Hi_NcParsers_LogicSyntaxs_Heidenhain_HeidenhainRtcpSyntax_FeedLimitKey">FeedLimitKey</a> — recorded, not simulated. FUNCTION TCPM
behavior arguments are recorded by the parsing syntax and warn
<code>Tcpm--ArgsNotSimulated</code> on activation.
</p>
<p>
Must run <b>after</b> <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ToolHeightOffsetSyntax.html">ToolHeightOffsetSyntax</a> /
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainToolOffsetSyntax.html">HeidenhainToolOffsetSyntax</a> and the coordinate-offset
syntaxes (mirroring the Fanuc G43.4 / Siemens TRAORI slot) and
<b>before</b> <a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainPivotTransformationSyntax.html">HeidenhainPivotTransformationSyntax</a>,
whose gate recognizes the <a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainRtcpSyntax.html#Hi_NcParsers_LogicSyntaxs_Heidenhain_HeidenhainRtcpSyntax_RtcpTerms">RtcpTerms</a> and folds the
kinematic pivot. Silently degrades to a plain <code>UnitZ · offset</code>
translation when <a class="xref" href="Hi.Numerical.Xyzabc.IMachineKinematics.html">IMachineKinematics</a> is absent.
</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainStockDeclarationSyntax.html">HeidenhainStockDeclarationSyntax</a></dt>
<dd><p>Heidenhain-specific: consumes the <code>Parsing[&ldquo;BLK FORM&rdquo;]</code> record
(workpiece blank declaration, present in virtually every klartext
file) into the brand-neutral <code>StockDeclaration</code> section —
recognized and recorded, not simulated. The simulation stock always
comes from the project's own workpiece setup, mirroring the HardNc
oracle which recognizes-and-skips the same lines; the structured
record keeps the declared blank readable for a future stock consumer
without feeding geometry today.</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainToolChangeSyntax.html">HeidenhainToolChangeSyntax</a></dt>
<dd><p>Heidenhain-specific: consumes the <code>Parsing[&ldquo;TOOL CALL&rdquo;]</code> record
(written by <a class="xref" href="Hi.NcParsers.ParsingSyntaxs.Heidenhain.HeidenhainToolCallSyntax.html">HeidenhainToolCallSyntax</a>)
into the shared <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ToolChangeSyntax.html#Hi_NcParsers_LogicSyntaxs_ToolChangeSyntax_SectionName">SectionName</a> section so
<a class="xref" href="Hi.NcParsers.Semantics.ToolChangeSemantic.html">ToolChangeSemantic</a> fires the tooling act. A
klartext <code>TOOL CALL</code> always performs the change — no separate M06
trigger exists — so <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ToolChangeSyntax.html#Hi_NcParsers_LogicSyntaxs_ToolChangeSyntax_IsChangeKey">IsChangeKey</a> is always
<code>true</code> with <code>Term = &ldquo;TOOL CALL&rdquo;</code>.</p>
<p>
The spindle-speed word (<code>S</code>) is relocated to the root of
<a class="xref" href="Hi.NcParsers.Keywords.IParsingDef.html#Hi_NcParsers_Keywords_IParsingDef_Parsing">Parsing</a> so the shared
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.SpindleSpeedSyntax.html">SpindleSpeedSyntax</a> — which must run after this syntax in
the Logic bundle — records it modally. Numeric tool ids are written as
ints (the act chain is int-keyed); non-numeric ids stay strings and
resolve (or warn) at the semantic layer.
</p>
<p>
P0 limits recorded as diagnostics: non-Z tool axis
(<code>ToolChange--AxisUnsupported</code>), non-zero DL/DR deltas
(<code>ToolChange--DeltaUnsupported</code>; zero deltas are consumed
silently), and a TOOL CALL without a tool id
(<code>ToolChange--MissingToolId</code>, e.g. a variable tool number the
parser could not capture).
</p>
<p>
Known P2 limitation: a quoted tool NAME that happens to spell a Q
token (<code>TOOL CALL "Q1" Z</code>) loses its quotes at capture, so the
evaluator substitutes the Q parameter's value and the numeric branch
below treats it as a tool number. Corpus-zero (real names are
<code>"B40R"</code>-style); fixing it needs the capture to preserve the
quoted-ness, which would change the P0-pinned record shape.
</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainToolOffsetSyntax.html">HeidenhainToolOffsetSyntax</a></dt>
<dd><p>Heidenhain-specific: klartext TOOL CALL always applies tool-length
compensation (there is no cancel word — HardNc compensates
unconditionally). On TOOL CALL blocks the effective height =
<a class="xref" href="Hi.NcParsers.Dependencys.IToolOffsetConfig.html#Hi_NcParsers_Dependencys_IToolOffsetConfig_GetToolHeightOffset_mm_System_Int32_">GetToolHeightOffset_mm(int)</a>(tool id) +
the TOOL CALL's DL delta; the shared <code>ToolHeightCompensation</code>
section is written (Term = <code>&ldquo;TOOL CALL&rdquo;</code>, OffsetId = tool id —
the offset id is documented as the Heidenhain tool number) and the
translation composes into the transform chain via the shared
<code>ToolHeightCompensation</code> source (mutual exclusion with the ISO
G43 sibling by same-source replace).</p>
<p>
Modal: on following blocks the section is re-resolved per block from
the table (mirroring the Siemens D sibling — give-way when a same
block ISO term took ownership; carry Term/OffsetId/Delta_mm
otherwise). Must sit after <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ToolHeightOffsetSyntax.html">ToolHeightOffsetSyntax</a> (the
ISO anchor — last writer wins on mixed-dialect blocks) and after
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainToolChangeSyntax.html">HeidenhainToolChangeSyntax</a> (reads its ToolChange
section), before the pivot/tilt syntaxes.
</p>
</dd>
</dl>