fix SoftNcRunner GM code normalization.

This commit is contained in:
2026-05-06 13:21:19 +08:00
parent 0fe9497552
commit 2f57932000
1238 changed files with 69405 additions and 22511 deletions
@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class ProgramXyzUtil | HiAPI-C# 2025 ">
<meta name="description" content="Shared utilities for and lookback and resolution. Used by , , and semantic resolvers that need position lookback.">
<meta name="description" content="Shared utilities for and lookback and resolution. Used by , , and semantic resolvers that need position lookback. Two strategies for &quot;what&#39;s the program coordinate at a block&#39;s endpoint?&quot; — both invert an MC value through an chain, but they pick the chain from different nodes: By current-state transform () — modal anchor is . Re-expresses an MC value (typically a predecessor&#39;s modal MC) into the current block&#39;s program frame using the current block&#39;s chain. Suitable for chain-change blocks where the spindle physically stays put while the chain (G54 swap, G68.2 activation, G43.4 toggle, tool-height change, ...) re-anchors the program frame; mirrors legacy HardNcLine.RebuildProgramXyzByMc. By corresponding-state transform () — modal anchor is . Recovers the program coordinate that nodeCarryingMc was originally commanded at, by inverting that same node&#39;s own transform on its own MC. Suitable for RTCP rotary-dynamic inheritance, where the modal invariant is &quot;tool tip in workpiece frame stays put while rotary axes turn&quot; — the recovered Vec3d carries forward as the next rotary block&#39;s modal ProgramXyz unchanged, regardless of how its PivotTransform differs. Both strategies yield the same Vec3d when prev and current share the same chain modal state; they only diverge across chain boundaries (RTCP toggle, coord-system swap, tilt activation) and at rotary motion (PivotTransform difference). Pick the wrong one and the result lands in a stale frame: Non-RTCP using &quot;corresponding&quot; — leaves the pre-chain-change values, so a block emitted right after G43.4 H03 would inherit ProgramXyz still in the G49 frame and the next motion&#39;s MC.Z drifts by the introduced tool-height offset. (This was the 2026-04-25 SoftNc / HardNc divergence on DemoPmcAirPlane/NC/02-ED6L20.NC.) RTCP using &quot;current&quot; — double-counts the rotary PivotTransform difference, so the inherited workpiece anchor rotates by the C delta on every rotary block. Direct callers of the two strategy helpers are rare — typically you call the dispatcher (block&#39;s own MC vs predecessor lookback, picks strategy from ) or (pure predecessor lookback).">
<link rel="icon" href="../img/HiAPI.favicon.ico">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
@@ -98,9 +98,63 @@ Class ProgramXyzUtil
</div>
<div class="markdown summary"><p>Shared utilities for <a class="xref" href="Hi.NcParsers.Keywords.IProgramXyzDef.html#Hi_NcParsers_Keywords_IProgramXyzDef_ProgramXyz">ProgramXyz</a> and
<a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateDef_MachineCoordinate">MachineCoordinate</a> lookback and resolution.
Used by <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzSyntax.html">ProgramXyzSyntax</a>, <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ReferenceReturnSyntax.html">ReferenceReturnSyntax</a>,
and semantic resolvers that need position lookback.</p>
<a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateStateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateStateDef_MachineCoordinateState">MachineCoordinateState</a> lookback and
resolution. Used by <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzSyntax.html">ProgramXyzSyntax</a>,
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ReferenceReturnSyntax.html">ReferenceReturnSyntax</a>, and semantic resolvers that need
position lookback.</p>
<p>
<b>Two strategies for "what's the program coordinate at a block's
endpoint?"</b> — both invert an MC value through an
<a class="xref" href="Hi.NcParsers.Keywords.ITransformationDef.html#Hi_NcParsers_Keywords_ITransformationDef_ProgramToMcTransform">ProgramToMcTransform</a> chain,
but they pick the chain from <i>different</i> nodes:
</p>
<ul><li>
<b>By current-state transform</b>
(<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ComputeProgramXyzByCurrentTransform_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__Hi_Geom_Vec3d_">ComputeProgramXyzByCurrentTransform(LazyLinkedListNode&lt;SyntaxPiece&gt;, Vec3d)</a>) — modal anchor is
<a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateStateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateStateDef_MachineCoordinateState">MachineCoordinateState</a>. Re-expresses an
MC value (typically a predecessor's modal MC) into the <i>current</i>
block's program frame using the current block's chain. Suitable for
chain-change blocks where the spindle physically stays put while the
chain (G54 swap, G68.2 activation, G43.4 toggle, tool-height change,
...) re-anchors the program frame; mirrors legacy
<code>HardNcLine.RebuildProgramXyzByMc</code>.
</li><li>
<b>By corresponding-state transform</b>
(<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ComputeProgramXyzByCorrespondingTransform_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__">ComputeProgramXyzByCorrespondingTransform(LazyLinkedListNode&lt;SyntaxPiece&gt;)</a>) — modal
anchor is <a class="xref" href="Hi.NcParsers.Keywords.IProgramXyzDef.html#Hi_NcParsers_Keywords_IProgramXyzDef_ProgramXyz">ProgramXyz</a>. Recovers the
program coordinate that <code>nodeCarryingMc</code> was originally commanded
at, by inverting <i>that same node's</i> own transform on its own MC.
Suitable for RTCP rotary-dynamic inheritance, where the modal
invariant is "tool tip in workpiece frame stays put while rotary axes
turn" — the recovered Vec3d carries forward as the next rotary block's
modal ProgramXyz unchanged, regardless of how its
<code>PivotTransform</code> differs.
</li></ul>
<p>
Both strategies yield the same Vec3d when prev and current share the
same chain modal state; they only diverge across chain boundaries
(RTCP toggle, coord-system swap, tilt activation) and at rotary motion
(PivotTransform difference). Pick the wrong one and the result lands
in a stale frame:
</p>
<ul><li>
Non-RTCP using "corresponding" — leaves the pre-chain-change values,
so a block emitted right after <code>G43.4 H03</code> would inherit
ProgramXyz still in the G49 frame and the next motion's MC.Z drifts
by the introduced tool-height offset. (This was the 2026-04-25
SoftNc / HardNc divergence on <code>DemoPmcAirPlane/NC/02-ED6L20.NC</code>.)
</li><li>
RTCP using "current" — double-counts the rotary
<code>PivotTransform</code> difference, so the inherited workpiece anchor
rotates by the C delta on every rotary block.
</li></ul>
<p>
Direct callers of the two strategy helpers are rare — typically you
call the dispatcher <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ResolveBlockProgramXyz_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__Hi_Geom_Vec3d_">ResolveBlockProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt;, Vec3d)</a> (block's own
MC vs predecessor lookback, picks strategy from
<a class="xref" href="Hi.NcParsers.Syntaxs.TransformationUtil.html#Hi_NcParsers_Syntaxs_TransformationUtil_HasDynamicEntry_System_Text_Json_Nodes_JsonObject_">HasDynamicEntry(JsonObject)</a>) or
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_GetLastProgramXyz_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__">GetLastProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt;)</a> (pure predecessor lookback).
</p>
</div>
<div class="markdown conceptual"></div>
@@ -156,6 +210,119 @@ and semantic resolvers that need position lookback.</p>
</h2>
<a id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ComputeProgramXyzByCorrespondingTransform_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.ComputeProgramXyzByCorrespondingTransform*"></a>
<h3 id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ComputeProgramXyzByCorrespondingTransform_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.ComputeProgramXyzByCorrespondingTransform(Hi.Common.Collections.LazyLinkedListNode{Hi.NcParsers.Syntaxs.SyntaxPiece})">
ComputeProgramXyzByCorrespondingTransform(LazyLinkedListNode&lt;SyntaxPiece&gt;)
</h3>
<div class="markdown level1 summary"><p><b>Strategy: by corresponding-state transform.</b> Recovers the
<a class="xref" href="Hi.NcParsers.Keywords.IProgramXyzDef.html#Hi_NcParsers_Keywords_IProgramXyzDef_ProgramXyz">ProgramXyz</a> that
<code class="paramref">nodeCarryingMc</code> was originally commanded at, by
inverting <i>that same node's</i>
<a class="xref" href="Hi.NcParsers.Keywords.ITransformationDef.html#Hi_NcParsers_Keywords_ITransformationDef_ProgramToMcTransform">ProgramToMcTransform</a> on
its own <a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateStateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateStateDef_MachineCoordinateState">MachineCoordinateState</a>.</p>
<p>
Modal invariant: <a class="xref" href="Hi.NcParsers.Keywords.IProgramXyzDef.html#Hi_NcParsers_Keywords_IProgramXyzDef_ProgramXyz">ProgramXyz</a> carries
forward (RTCP rotary modal) — the workpiece-frame anchor survives
downstream rotary motion regardless of how the next block's
<code>PivotTransform</code> differs, so the next rotary-dynamic block
can adopt this Vec3d unchanged as its modal ProgramXyz.
</p>
<p>
Returns null when <code class="paramref">nodeCarryingMc</code> has no usable
MC. Called from the RTCP branch of
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_GetLastProgramXyz_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__">GetLastProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt;)</a> and from
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ResolveBlockProgramXyz_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__Hi_Geom_Vec3d_">ResolveBlockProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt;, Vec3d)</a> when the dispatched node has
its own MC.
</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static Vec3d ComputeProgramXyzByCorrespondingTransform(LazyLinkedListNode&lt;SyntaxPiece&gt; nodeCarryingMc)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>nodeCarryingMc</code> <a class="xref" href="Hi.Common.Collections.LazyLinkedListNode-1.html">LazyLinkedListNode</a>&lt;<a class="xref" href="Hi.NcParsers.Syntaxs.SyntaxPiece.html">SyntaxPiece</a>&gt;</dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a></dt>
<dd></dd>
</dl>
<a id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ComputeProgramXyzByCurrentTransform_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.ComputeProgramXyzByCurrentTransform*"></a>
<h3 id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ComputeProgramXyzByCurrentTransform_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__Hi_Geom_Vec3d_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.ComputeProgramXyzByCurrentTransform(Hi.Common.Collections.LazyLinkedListNode{Hi.NcParsers.Syntaxs.SyntaxPiece},Hi.Geom.Vec3d)">
ComputeProgramXyzByCurrentTransform(LazyLinkedListNode&lt;SyntaxPiece&gt;, Vec3d)
</h3>
<div class="markdown level1 summary"><p><b>Strategy: by current-state transform.</b> Re-expresses
<code class="paramref">mc</code> into <code class="paramref">currentNode</code>'s program
frame by inverting <code class="paramref">currentNode</code>'s own
<a class="xref" href="Hi.NcParsers.Keywords.ITransformationDef.html#Hi_NcParsers_Keywords_ITransformationDef_ProgramToMcTransform">ProgramToMcTransform</a>
chain.</p>
<p>
Modal invariant: <a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateStateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateStateDef_MachineCoordinateState">MachineCoordinateState</a>
carries forward — between the source of <code class="paramref">mc</code> and
<code class="paramref">currentNode</code>, the spindle physically stays put
while the chain (G54 swap, G68.2 activation, G43.4 toggle,
tool-height change, ...) re-anchors the program frame. Result is
the program coordinate that, when transformed by
<code class="paramref">currentNode</code>'s chain, yields
<code class="paramref">mc</code> back.
</p>
<p>
Mirrors legacy <code>HardNcLine.RebuildProgramXyzByMc</code>; called
from the non-RTCP branch of <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_GetLastProgramXyz_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__">GetLastProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt;)</a>.
</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static Vec3d ComputeProgramXyzByCurrentTransform(LazyLinkedListNode&lt;SyntaxPiece&gt; currentNode, Vec3d mc)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>currentNode</code> <a class="xref" href="Hi.Common.Collections.LazyLinkedListNode-1.html">LazyLinkedListNode</a>&lt;<a class="xref" href="Hi.NcParsers.Syntaxs.SyntaxPiece.html">SyntaxPiece</a>&gt;</dt>
<dd></dd>
<dt><code>mc</code> <a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a></dt>
<dd></dd>
</dl>
<a id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_FindPreviousMc_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.FindPreviousMc*"></a>
<h3 id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_FindPreviousMc_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.FindPreviousMc(Hi.Common.Collections.LazyLinkedListNode{Hi.NcParsers.Syntaxs.SyntaxPiece})">
@@ -163,7 +330,7 @@ and semantic resolvers that need position lookback.</p>
</h3>
<div class="markdown level1 summary"><p>Finds the most recent <a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateDef_MachineCoordinate">MachineCoordinate</a>
<div class="markdown level1 summary"><p>Finds the most recent <a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateStateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateStateDef_MachineCoordinateState">MachineCoordinateState</a>
from previous <a class="xref" href="Hi.NcParsers.Syntaxs.SyntaxPiece.html">SyntaxPiece</a> nodes.
Returns null if no previous position found.</p>
</div>
@@ -197,20 +364,96 @@ Returns null if no previous position found.</p>
<a id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_FindPreviousMcXyzabc_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.FindPreviousMcXyzabc*"></a>
<h3 id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_FindPreviousMcXyzabc_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.FindPreviousMcXyzabc(Hi.Common.Collections.LazyLinkedListNode{Hi.NcParsers.Syntaxs.SyntaxPiece})">
FindPreviousMcXyzabc(LazyLinkedListNode&lt;SyntaxPiece&gt;)
<h3 id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_FindPreviousMcXyzabc_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__Hi_NcParsers_Dependencys_IMachineAxisConfig_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.FindPreviousMcXyzabc(Hi.Common.Collections.LazyLinkedListNode{Hi.NcParsers.Syntaxs.SyntaxPiece},Hi.NcParsers.Dependencys.IMachineAxisConfig)">
FindPreviousMcXyzabc(LazyLinkedListNode&lt;SyntaxPiece&gt;, IMachineAxisConfig)
</h3>
<div class="markdown level1 summary"><p>Finds the most recent <a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateDef_MachineCoordinate">MachineCoordinate</a>
<div class="markdown level1 summary"><p>Finds the most recent <a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateStateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateStateDef_MachineCoordinateState">MachineCoordinateState</a>
XYZABC from previous nodes as <a class="xref" href="Hi.Geom.DVec3d.html">DVec3d</a>.
Point = XYZ (mm), Normal = ABC (radians, converted from degrees in JSON).
Returns null if no previous position found.</p>
Point = XYZ (mm), Normal = ABC (radians, converted from degrees in JSON).</p>
<p>
XYZ is taken from the first previous block whose MC has any of
X/Y/Z set (typical motion-emitting block). ABC is then backfilled
<b>per axis</b> for axes the machine actually has: if the
XYZ-carrying block lacks a particular rotary value, we continue
walking back to find the last block that wrote that axis (modal
rotary state). This matches NC semantics — unchanged rotary axes
carry forward silently — and prevents NaN rotary deltas from
stopping <a class="xref" href="Hi.NcParsers.Semantics.ClLinearMotionSemantic.html">ClLinearMotionSemantic</a>'s
duration computation in RTCP contours where the XYZ block right
before the current one didn't record ABC.
</p>
<p>
<code class="paramref">axisConfig</code> scopes the rotary-backfill to the
machine's declared rotary axes (via
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.RotaryAxisUtil.html#Hi_NcParsers_LogicSyntaxs_RotaryAxisUtil_GetRotaryAxes_Hi_NcParsers_Dependencys_IMachineAxisConfig_">GetRotaryAxes(IMachineAxisConfig)</a>): non-rotary axes stay
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.double.nan">NaN</a> and skip backward walking entirely. When
<code class="paramref">axisConfig</code> is null (callers without the
dependency — e.g. legacy tests), all three A/B/C are attempted,
matching the pre-axisConfig behaviour.
</p>
<p>
Returns null if no previous MC with XYZ is found at all.
Axes that have never been set stay <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.double.nan">NaN</a>.
</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static DVec3d FindPreviousMcXyzabc(LazyLinkedListNode&lt;SyntaxPiece&gt; node)</code></pre>
<pre><code class="lang-csharp hljs">public static DVec3d FindPreviousMcXyzabc(LazyLinkedListNode&lt;SyntaxPiece&gt; node, IMachineAxisConfig axisConfig = null)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>node</code> <a class="xref" href="Hi.Common.Collections.LazyLinkedListNode-1.html">LazyLinkedListNode</a>&lt;<a class="xref" href="Hi.NcParsers.Syntaxs.SyntaxPiece.html">SyntaxPiece</a>&gt;</dt>
<dd></dd>
<dt><code>axisConfig</code> <a class="xref" href="Hi.NcParsers.Dependencys.IMachineAxisConfig.html">IMachineAxisConfig</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="Hi.Geom.DVec3d.html">DVec3d</a></dt>
<dd></dd>
</dl>
<a id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_FindPreviousStoredProgramXyz_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.FindPreviousStoredProgramXyz*"></a>
<h3 id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_FindPreviousStoredProgramXyz_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.FindPreviousStoredProgramXyz(Hi.Common.Collections.LazyLinkedListNode{Hi.NcParsers.Syntaxs.SyntaxPiece})">
FindPreviousStoredProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt;)
</h3>
<div class="markdown level1 summary"><p>Finds the most recent <i>stored</i> <a class="xref" href="Hi.NcParsers.Keywords.IProgramXyzDef.html#Hi_NcParsers_Keywords_IProgramXyzDef_ProgramXyz">ProgramXyz</a>
from previous <a class="xref" href="Hi.NcParsers.Syntaxs.SyntaxPiece.html">SyntaxPiece</a> nodes — a raw-value lookback
that returns whatever was written on disk, without MC-inversion or
frame-change reconstruction.</p>
<p>
Contrast with <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_GetLastProgramXyz_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__">GetLastProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt;)</a>, which reconstructs
the inherited program position as
<code>prev.MC × inverse(transform)</code> and is sensitive to RTCP /
chain-change boundaries. This helper is the simple parallel of
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_FindPreviousMc_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__">FindPreviousMc(LazyLinkedListNode&lt;SyntaxPiece&gt;)</a> — use it when a caller specifically
needs "what ProgramXyz did the last block write" (e.g. the
<a class="xref" href="Hi.NcParsers.InspectionSyntaxs.ProgramXyzBackfillSyntax.html">ProgramXyzBackfillSyntax</a> change check).
</p>
Returns null if no predecessor has <a class="xref" href="Hi.NcParsers.Keywords.IProgramXyzDef.html#Hi_NcParsers_Keywords_IProgramXyzDef_ProgramXyz">ProgramXyz</a>.
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static Vec3d FindPreviousStoredProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt; node)</code></pre>
</div>
<h4 class="section">Parameters</h4>
@@ -221,7 +464,7 @@ Returns null if no previous position found.</p>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="Hi.Geom.DVec3d.html">DVec3d</a></dt>
<dt><a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a></dt>
<dd></dd>
</dl>
@@ -242,9 +485,35 @@ Returns null if no previous position found.</p>
</h3>
<div class="markdown level1 summary"><p>Gets the last ProgramXyz using the composed transform found from
previous nodes (FindPrevious pattern). Use when current node's
transform is not yet available.</p>
<div class="markdown level1 summary"><p>Gets the modal ProgramXyz inherited by <code class="paramref">node</code> from
the most recent predecessor with an
<a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateStateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateStateDef_MachineCoordinateState">MachineCoordinateState</a>. Dispatches
between the two strategies documented on the class summary based on
whether <code class="paramref">node</code>'s
<a class="xref" href="Hi.NcParsers.Keywords.ITransformationDef.html#Hi_NcParsers_Keywords_ITransformationDef_ProgramToMcTransform">ProgramToMcTransform</a> chain carries
any <a class="xref" href="Hi.NcParsers.Syntaxs.TransformationUtil.html#Hi_NcParsers_Syntaxs_TransformationUtil_KindDynamic">KindDynamic</a> entry
(queried via <a class="xref" href="Hi.NcParsers.Syntaxs.TransformationUtil.html#Hi_NcParsers_Syntaxs_TransformationUtil_HasDynamicEntry_System_Text_Json_Nodes_JsonObject_">HasDynamicEntry(JsonObject)</a>):</p>
<ul><li>
Has a Dynamic entry (RTCP rotary modal) →
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ComputeProgramXyzByCorrespondingTransform_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__">ComputeProgramXyzByCorrespondingTransform(LazyLinkedListNode&lt;SyntaxPiece&gt;)</a> on the
predecessor (recover prev's commanded ProgramXyz; carries forward
unchanged because workpiece-frame tool tip is the modal anchor).
</li><li>
All entries Static (chain-change / non-RTCP) →
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ComputeProgramXyzByCurrentTransform_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__Hi_Geom_Vec3d_">ComputeProgramXyzByCurrentTransform(LazyLinkedListNode&lt;SyntaxPiece&gt;, Vec3d)</a> with
<code class="paramref">node</code>'s own transform on the predecessor's MC
(re-express prev MC in current program frame; MC is the modal
anchor while the chain re-frames around it).
</li></ul>
<p>
When prev and current share the same chain modal state both
strategies agree, so the discriminator only matters at chain
boundaries / rotary motion.
</p>
<p>
Returns <a class="xref" href="Hi.Geom.Vec3d.html#Hi_Geom_Vec3d_Zero">Zero</a> only when no predecessor has a
usable MC (i.e. the start of the program with no motion emitted).
</p>
</div>
<div class="markdown level1 conceptual"></div>
@@ -274,47 +543,6 @@ transform is not yet available.</p>
<a id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_GetLastProgramXyz_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.GetLastProgramXyz*"></a>
<h3 id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_GetLastProgramXyz_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__Hi_Geom_Mat4d_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.GetLastProgramXyz(Hi.Common.Collections.LazyLinkedListNode{Hi.NcParsers.Syntaxs.SyntaxPiece},Hi.Geom.Mat4d)">
GetLastProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt;, Mat4d)
</h3>
<div class="markdown level1 summary"><p>Gets the last ProgramXyz by finding the last MachineCoordinate from
backward nodes and inverse-transforming with the given Transformation.
This handles Transformation changes between blocks correctly.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static Vec3d GetLastProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt; node, Mat4d currentTransformation)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>node</code> <a class="xref" href="Hi.Common.Collections.LazyLinkedListNode-1.html">LazyLinkedListNode</a>&lt;<a class="xref" href="Hi.NcParsers.Syntaxs.SyntaxPiece.html">SyntaxPiece</a>&gt;</dt>
<dd></dd>
<dt><code>currentTransformation</code> <a class="xref" href="Hi.Geom.Mat4d.html">Mat4d</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a></dt>
<dd></dd>
</dl>
<a id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ReadMcXyzabc_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.ReadMcXyzabc*"></a>
<h3 id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ReadMcXyzabc_System_Text_Json_Nodes_JsonObject_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.ReadMcXyzabc(System.Text.Json.Nodes.JsonObject)">
@@ -322,7 +550,7 @@ This handles Transformation changes between blocks correctly.</p>
</h3>
<div class="markdown level1 summary"><p>Reads XYZABC from a <a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateDef_MachineCoordinate">MachineCoordinate</a>
<div class="markdown level1 summary"><p>Reads XYZABC from a <a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateStateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateStateDef_MachineCoordinateState">MachineCoordinateState</a>
section as <a class="xref" href="Hi.Geom.DVec3d.html">DVec3d</a>. Point = XYZ (mm),
Normal = ABC (radians, converted from degrees in JSON).
Missing axes are <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.double.nan">NaN</a>.
@@ -356,10 +584,88 @@ Returns null if the section doesn't exist or has no XYZ.</p>
<a id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ResolveBlockProgramXyz_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.ResolveBlockProgramXyz*"></a>
<h3 id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ResolveBlockProgramXyz_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__Hi_Geom_Vec3d_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.ResolveBlockProgramXyz(Hi.Common.Collections.LazyLinkedListNode{Hi.NcParsers.Syntaxs.SyntaxPiece},Hi.Geom.Vec3d)">
ResolveBlockProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt;, Vec3d)
</h3>
<div class="markdown level1 summary"><p>Resolves the <a class="xref" href="Hi.NcParsers.Keywords.IProgramXyzDef.html#Hi_NcParsers_Keywords_IProgramXyzDef_ProgramXyz">ProgramXyz</a> at
<code class="paramref">node</code>'s endpoint — i.e. what
<a class="xref" href="Hi.NcParsers.InspectionSyntaxs.ProgramXyzBackfillSyntax.html">ProgramXyzBackfillSyntax</a> would write on
<code class="paramref">node</code>. Dispatcher; the actual inversion math runs
inside one of the two strategy helpers documented on the class
summary:</p>
<ul><li>
<code class="paramref">node</code> has its own
<a class="xref" href="Hi.NcParsers.Keywords.IMachineCoordinateStateDef.html#Hi_NcParsers_Keywords_IMachineCoordinateStateDef_MachineCoordinateState">MachineCoordinateState</a> XYZ →
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ComputeProgramXyzByCorrespondingTransform_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__">ComputeProgramXyzByCorrespondingTransform(LazyLinkedListNode&lt;SyntaxPiece&gt;)</a> on
<code class="paramref">node</code> itself (its own MC and own transform; the
"current" / "corresponding" distinction collapses since both come
from the same node).
</li><li>
<code class="paramref">node</code> has no own MC and
<code class="paramref">prevStored</code> is non-null →
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_GetLastProgramXyz_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__">GetLastProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt;)</a> walks back to the most recent
predecessor with MC and dispatches strategy from
<code class="paramref">node</code>'s
<a class="xref" href="Hi.NcParsers.Syntaxs.TransformationUtil.html#Hi_NcParsers_Syntaxs_TransformationUtil_HasDynamicEntry_System_Text_Json_Nodes_JsonObject_">HasDynamicEntry(JsonObject)</a> result.
</li><li>
Both empty → return null; callers must not fabricate a spurious
origin on the very first block.
</li></ul>
<p>
Shared by <a class="xref" href="Hi.NcParsers.InspectionSyntaxs.ProgramXyzBackfillSyntax.html">ProgramXyzBackfillSyntax</a>
(computing the snapshot value to write on <code class="paramref">node</code>)
and <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcXyzFallbackSyntax.html">McAbcXyzFallbackSyntax</a> (computing
<a class="xref" href="Hi.Common.Collections.LazyLinkedListNode-1.html#Hi_Common_Collections_LazyLinkedListNode_1_Previous">Previous</a>'s would-be snapshot
to inherit on the current rotary-dynamic block — the Logic-stage
caller cannot read prev's stored ProgramXyz because PostSyntaxs
run after the whole Logic chain finishes).
</p>
<p>
<code class="paramref">prevStored</code> for the second use is taken from
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_FindPreviousStoredProgramXyz_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__">FindPreviousStoredProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt;)</a> on
<code class="paramref">node</code>'s predecessor — the
predecessor-of-predecessor's stored ProgramXyz — only as a guard
against the spurious-origin case.
</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static Vec3d ResolveBlockProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt; node, Vec3d prevStored)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>node</code> <a class="xref" href="Hi.Common.Collections.LazyLinkedListNode-1.html">LazyLinkedListNode</a>&lt;<a class="xref" href="Hi.NcParsers.Syntaxs.SyntaxPiece.html">SyntaxPiece</a>&gt;</dt>
<dd></dd>
<dt><code>prevStored</code> <a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="Hi.Geom.Vec3d.html">Vec3d</a></dt>
<dd></dd>
</dl>
<a id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ResolveProgramXyz_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.ResolveProgramXyz*"></a>
<h3 id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ResolveProgramXyz_System_Text_Json_Nodes_JsonNode_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__Hi_Geom_Mat4d_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.ResolveProgramXyz(System.Text.Json.Nodes.JsonNode,Hi.Common.Collections.LazyLinkedListNode{Hi.NcParsers.Syntaxs.SyntaxPiece},Hi.Geom.Mat4d)">
ResolveProgramXyz(JsonNode, LazyLinkedListNode&lt;SyntaxPiece&gt;, Mat4d)
<h3 id="Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_ResolveProgramXyz_System_Text_Json_Nodes_JsonNode_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__Hi_NcParsers_Sentence_Hi_NcParsers_NcDiagnosticProgress_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.ResolveProgramXyz(System.Text.Json.Nodes.JsonNode,Hi.Common.Collections.LazyLinkedListNode{Hi.NcParsers.Syntaxs.SyntaxPiece},Hi.NcParsers.Sentence,Hi.NcParsers.NcDiagnosticProgress)">
ResolveProgramXyz(JsonNode, LazyLinkedListNode&lt;SyntaxPiece&gt;, Sentence, NcDiagnosticProgress)
</h3>
@@ -369,7 +675,7 @@ Fills missing axes from last program position via lookback.</p>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static Vec3d ResolveProgramXyz(JsonNode xyzSource, LazyLinkedListNode&lt;SyntaxPiece&gt; syntaxPieceNode, Mat4d transformation)</code></pre>
<pre><code class="lang-csharp hljs">public static Vec3d ResolveProgramXyz(JsonNode xyzSource, LazyLinkedListNode&lt;SyntaxPiece&gt; syntaxPieceNode, Sentence sentence, NcDiagnosticProgress diag)</code></pre>
</div>
<h4 class="section">Parameters</h4>
@@ -381,10 +687,10 @@ Fills missing axes from last program position via lookback.</p>
<dt><code>syntaxPieceNode</code> <a class="xref" href="Hi.Common.Collections.LazyLinkedListNode-1.html">LazyLinkedListNode</a>&lt;<a class="xref" href="Hi.NcParsers.Syntaxs.SyntaxPiece.html">SyntaxPiece</a>&gt;</dt>
<dd><p>Current node for lookback.</p>
</dd>
<dt><code>transformation</code> <a class="xref" href="Hi.Geom.Mat4d.html">Mat4d</a></dt>
<dd><p>Current composed ProgramToMc transform,
needed by <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzUtil.html#Hi_NcParsers_LogicSyntaxs_ProgramXyzUtil_GetLastProgramXyz_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__Hi_Geom_Mat4d_">GetLastProgramXyz(LazyLinkedListNode&lt;SyntaxPiece&gt;, Mat4d)</a> for inverse lookback.</p>
</dd>
<dt><code>sentence</code> <a class="xref" href="Hi.NcParsers.Sentence.html">Sentence</a></dt>
<dd></dd>
<dt><code>diag</code> <a class="xref" href="Hi.NcParsers.NcDiagnosticProgress.html">NcDiagnosticProgress</a></dt>
<dd></dd>
</dl>
<h4 class="section">Returns</h4>