This commit is contained in:
2026-09-15 01:12:50 +08:00
parent 2db889ad89
commit 1a75503105
99 changed files with 4168 additions and 726 deletions
@@ -507,6 +507,33 @@ After this syntax, all axis values in the working paths are absolute —
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramXyzSyntax.html">ProgramXyzSyntax</a> can consume them without
incremental logic.
</p>
<p>
Rotary words (A/B/C) at the <code>Parsing</code> root never reach this
syntax — <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a> consumes them upstream and follows
the modal G91 itself. Inside a nested record they do
(<code>G91 G28 C10.</code> — the <code>Parsing.G28</code> intermediate), and a
rotary axis has no program→MC transform, so its anchor is the
previous modal angle
(<a class="xref" href="Hi.NcParsers.LogicSyntaxs.RotaryAxisUtil.html#Hi_NcParsers_LogicSyntaxs_RotaryAxisUtil_FindPreviousMcAxisDeg_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__System_String_">FindPreviousMcAxisDeg(LazyLinkedListNode&lt;SyntaxPiece&gt;, string)</a>) rather than a
component of the program XYZ: the intermediate lands at
current + 10°, the way HardNc's <code>ParseG28</code> reads it against
the previous MC. A never-set rotary axis anchors at 0.
</p>
<p>
The rewrite is in place, and the modal <a class="xref" href="Hi.NcParsers.Keywords.Positioning.html">Positioning</a>
section keeps saying <code>G91</code> (the next block's lookback needs it),
so a converted word is indistinguishable from a programmed absolute.
Every word this syntax converts is therefore also recorded, as
programmed, in the one-shot block-root <a class="xref" href="Hi.NcParsers.Keywords.IncrementalWords.html">IncrementalWords</a>
section, shaped like the <code>Parsing</code> tree it came from
(<code>{ "X": 10, "G28": { "C": 10 } }</code>). The record doubles as the
idempotency guard: a word already listed at its path is left alone,
so a second pass over the same block — a project file whose
serialized list carries two instances, a re-run over a frozen piece
— cannot add the anchor twice. Coded-position words are not recorded
(they are not increments of a coordinate; their trace is the
rewritten override entry).
</p>
</dd>
</dl>
<dl class="jumplist">
@@ -743,14 +770,19 @@ to resolve against (first rotary value in the stream) is reported as
path.
</p>
<p>
Per-word incremental override: an <a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_Incremental">Incremental</a>
entry (Siemens <code>IC()</code>, klartext <code>IC+270</code>) is a signed
traverse by definition — <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a> already wrote
anchor + delta — so this pass keeps that value verbatim for the
axis instead of folding it into the ±180° window (a +270° chain
dimension must not become a -90° swing). Incremental entries on
non-modular axes need no warning: the literal value is what the
axis would do anyway.
Incremental words: a rotary word programmed as an increment —
per-word (Siemens <code>IC()</code>, klartext <code>IC+270</code>) or a bare
word under modal <code>G91</code> — is a signed traverse by definition.
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a> already wrote anchor + delta into the MC
and listed the axis in the one-shot <a class="xref" href="Hi.NcParsers.Keywords.IncrementalWords.html">IncrementalWords</a>
record; this pass reads that record — and only that record — and
keeps the listed axes verbatim instead of folding them into the ±180°
window (a +270° chain dimension must not become a -90° swing). A
listed non-modular axis needs nothing: the literal value is what the
axis would do anyway. A rotary value the block carries without a
word (lookback fill, or an absolute target another writer put there
— <code>G53.1</code>, the Heidenhain <code>PLANE</code> syntax) is not listed
and keeps the default window even under G91.
</p>
</dd>
</dl>
@@ -811,6 +843,28 @@ math. Brands that never write the section keep the exact legacy
behavior.
</p>
<p>
Modal G91: a rotary word with <b>no</b> per-word entry follows the
block's <a class="xref" href="Hi.NcParsers.Keywords.Positioning.html">Positioning</a> state (written ahead of this
syntax by <a class="xref" href="Hi.NcParsers.LogicSyntaxs.PositioningSyntax.html">PositioningSyntax</a> on every brand list) the
way the linear words follow it in
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.IncrementalResolveSyntax.html">IncrementalResolveSyntax</a> — under <code>G91</code> it takes
the same anchor + delta path as the <a class="xref" href="Hi.NcParsers.Keywords.Positioning.html#Hi_NcParsers_Keywords_Positioning_Incremental">Incremental</a>
override, so <code>G91 … C20.</code> repeated turns the table 20° further
each block (Fanuc / Siemens / Heidenhain DIN-ISO all read an
incremental rotary word as a signed traverse; the
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcCyclicPathSyntax.html">McAbcCyclicPathSyntax</a> tail-pass keeps it literal for
the axes the <a class="xref" href="Hi.NcParsers.Keywords.IncrementalWords.html">IncrementalWords</a> record lists). A per-word entry of any
value beats the modal state for its word (<code>G91 C=AC(90)</code> is
absolute). Rotary values another writer put on the block without a
word — <a class="xref" href="Hi.NcParsers.LogicSyntaxs.G53p1RotaryPositionSyntax.html">G53p1RotaryPositionSyntax</a>, the Heidenhain
<code>PLANE</code> syntax — are absolute targets and are not touched.
HardNc differs here by design of its own: <code>HardNcLine.BuildOrdinaryMcAbc</code>
writes the word as an absolute angle under G91 and warns
(<i>"G91 is not effect for commands ABC"</i>), so the two engines
diverge on G91 rotary words — the parity fixtures assert the
SoftNc leg only.
</p>
<p>
Coded-position overrides (Siemens
<code>CAC()</code>/<code>CIC()</code>/<code>CDC()</code>/<code>CACP()</code>/<code>CACN()</code>)
carry an indexing position <b>number</b> instead of an angle: the
@@ -836,7 +890,17 @@ that distinction (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.CannedCycleRes
active canned cycle on a rotary-only block,
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.text.json.nodes.jsonobject">WriteCompoundMotion(JsonObject, string, JsonArray, Vec3d)</a> riding the
block's ABC on the cycle's pre-positioning item) read the record; the
section is never modal-carried.
section is never modal-carried. Its sibling
<a class="xref" href="Hi.NcParsers.Keywords.IncrementalWords.html">IncrementalWords</a> records, with the programmed delta,
the rotary words this syntax accumulated as increments (per-word
<code>IC()</code>/<code>IC+</code> or a bare word under modal G91): the MC
value is an absolute angle from then on and the modal
<a class="xref" href="Hi.NcParsers.Keywords.Positioning.html">Positioning</a> still says G91, so without the record an
accumulated word would read like a programmed absolute.
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.IncrementalResolveSyntax.html">IncrementalResolveSyntax</a> adds the block's linear
increments to the same record later in the list, and
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcCyclicPathSyntax.html">McAbcCyclicPathSyntax</a> reads it to pass the listed axes
through the shortest-path wrap literally.
</p>
<p>
Must be placed <b>before</b> <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McXyzSyntax.html">McXyzSyntax</a> so syntaxes
@@ -1364,6 +1428,7 @@ for subsequent block lookback.
<dd><p>Shared utilities for rotary axis (A/B/C) resolution.
Used by <a class="xref" href="Hi.NcParsers.LogicSyntaxs.G53p1RotaryPositionSyntax.html">G53p1RotaryPositionSyntax</a>,
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a>, <a class="xref" href="Hi.NcParsers.LogicSyntaxs.IsoG68p2TiltSyntax.html">IsoG68p2TiltSyntax</a>,
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.IncrementalResolveSyntax.html">IncrementalResolveSyntax</a>
and other syntaxes that read or write rotary axis values.</p>
</dd>
</dl>