This commit is contained in:
2026-09-09 18:06:21 +08:00
parent 161af68fe3
commit 45b9f9ed5d
79 changed files with 1167 additions and 1532 deletions
@@ -0,0 +1,319 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Class StrokeLimitUtil | HiAPI-C# 2025 </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class StrokeLimitUtil | HiAPI-C# 2025 ">
<meta name="description" content="Load-time audit helpers for : which machine-coordinate axes the chain has, and which of them the stroke limit check cannot judge because no limit is configured. Both checks — the per-block and the per-step — compare only axes that carry a limit, so a machine file without limits passes every position silently while EnableStrokeLimitCheck reads as on. The session begin reports that gap once through these helpers.">
<link rel="icon" href="../img/HiAPI.favicon.ico">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="ManagedReference">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../img/HiAPI.logo.png" alt="">
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="Hi.NcParsers.Dependencys.StrokeLimitUtil">
<h1 id="Hi_NcParsers_Dependencys_StrokeLimitUtil" data-uid="Hi.NcParsers.Dependencys.StrokeLimitUtil" class="text-break">
Class StrokeLimitUtil
</h1>
<div class="facts text-secondary">
<dl><dt>Namespace</dt><dd><a class="xref" href="Hi.html">Hi</a>.<a class="xref" href="Hi.NcParsers.html">NcParsers</a>.<a class="xref" href="Hi.NcParsers.Dependencys.html">Dependencys</a></dd></dl>
<dl><dt>Assembly</dt><dd>HiMech.dll</dd></dl>
</div>
<div class="markdown summary"><p>Load-time audit helpers for <a class="xref" href="Hi.NcParsers.Dependencys.IStrokeLimitConfig.html">IStrokeLimitConfig</a>: which
machine-coordinate axes the chain has, and which of them the stroke limit
check cannot judge because no limit is configured. Both checks — the
per-block <a class="xref" href="Hi.NcParsers.Semantics.StrokeLimitCheckSemantic.html">StrokeLimitCheckSemantic</a> and the per-step
<a class="xref" href="Hi.NcParsers.Dependencys.IStrokeLimitConfig.html#Hi_NcParsers_Dependencys_IStrokeLimitConfig_CheckStrokeLimit_Hi_Geom_DVec3d_System_IProgress_Hi_Common_Messages_IMessage__">CheckStrokeLimit(DVec3d, IProgress&lt;IMessage&gt;)</a> — compare only axes that
carry a limit, so a machine file without limits passes every position
silently while <code>EnableStrokeLimitCheck</code> reads as on. The session
begin reports that gap once through these helpers.</p>
</div>
<div class="markdown conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static class StrokeLimitUtil</code></pre>
</div>
<dl class="typelist inheritance">
<dt>Inheritance</dt>
<dd>
<div><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object">object</a></div>
<div><span class="xref">StrokeLimitUtil</span></div>
</dd>
</dl>
<dl class="typelist inheritedMembers">
<dt>Inherited Members</dt>
<dd>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object)">object.Equals(object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gethashcode">object.GetHashCode()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone">object.MemberwiseClone()</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object, object)</a>
</div>
<div>
<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.object.tostring">object.ToString()</a>
</div>
</dd></dl>
<h2 class="section" id="fields">Fields
</h2>
<h3 id="Hi_NcParsers_Dependencys_StrokeLimitUtil_McAxisNames" data-uid="Hi.NcParsers.Dependencys.StrokeLimitUtil.McAxisNames">
McAxisNames
</h3>
<div class="markdown level1 summary"><p>Machine-coordinate axis names, linear first then rotary.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static readonly string[] McAxisNames</code></pre>
</div>
<h4 class="section">Field Value</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a>[]</dt>
<dd></dd>
</dl>
<h2 class="section" id="methods">Methods
</h2>
<a id="Hi_NcParsers_Dependencys_StrokeLimitUtil_DescribeUnlimitedAxes_" data-uid="Hi.NcParsers.Dependencys.StrokeLimitUtil.DescribeUnlimitedAxes*"></a>
<h3 id="Hi_NcParsers_Dependencys_StrokeLimitUtil_DescribeUnlimitedAxes_System_Collections_Generic_IEnumerable_System_String__System_Func_System_String_System_Nullable_System_Double___System_Func_System_String_System_Nullable_System_Double___" data-uid="Hi.NcParsers.Dependencys.StrokeLimitUtil.DescribeUnlimitedAxes(System.Collections.Generic.IEnumerable{System.String},System.Func{System.String,System.Nullable{System.Double}},System.Func{System.String,System.Nullable{System.Double}})">
DescribeUnlimitedAxes(IEnumerable&lt;string&gt;, Func&lt;string, double?&gt;, Func&lt;string, double?&gt;)
</h3>
<div class="markdown level1 summary"><p>Describes the axes among <code class="paramref">axisNames</code> that the stroke
limit check cannot judge: an axis with neither end configured is
listed by name, an axis with one end only is listed with the missing
end (<code>&quot;Z (no negative limit)&quot;</code>). Empty when every axis has both
ends. A limit of NaN or ±infinity counts as not configured (the legacy
<code>HardNcEnv</code> boxes default to an infinite box).</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static List&lt;string&gt; DescribeUnlimitedAxes(IEnumerable&lt;string&gt; axisNames, Func&lt;string, double?&gt; positiveLimit, Func&lt;string, double?&gt; negativeLimit)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>axisNames</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.collections.generic.ienumerable-1">IEnumerable</a>&lt;<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a>&gt;</dt>
<dd><p>The axes to audit, normally <a class="xref" href="Hi.NcParsers.Dependencys.StrokeLimitUtil.html#Hi_NcParsers_Dependencys_StrokeLimitUtil_GetChainAxisNames_Hi_Numerical_Xyzabc_IXyzabcChain_System_Boolean_">GetChainAxisNames(IXyzabcChain, bool)</a>.</p>
</dd>
<dt><code>positiveLimit</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.func-2">Func</a>&lt;<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a>, <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.double">double</a>?&gt;</dt>
<dd><p>Positive-end limit per axis; null when not configured.</p>
</dd>
<dt><code>negativeLimit</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.func-2">Func</a>&lt;<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a>, <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.double">double</a>?&gt;</dt>
<dd><p>Negative-end limit per axis; null when not configured.</p>
</dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.collections.generic.list-1">List</a>&lt;<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a>&gt;</dt>
<dd></dd>
</dl>
<a id="Hi_NcParsers_Dependencys_StrokeLimitUtil_GetChainAxisNames_" data-uid="Hi.NcParsers.Dependencys.StrokeLimitUtil.GetChainAxisNames*"></a>
<h3 id="Hi_NcParsers_Dependencys_StrokeLimitUtil_GetChainAxisNames_Hi_Numerical_Xyzabc_IXyzabcChain_System_Boolean_" data-uid="Hi.NcParsers.Dependencys.StrokeLimitUtil.GetChainAxisNames(Hi.Numerical.Xyzabc.IXyzabcChain,System.Boolean)">
GetChainAxisNames(IXyzabcChain, bool)
</h3>
<div class="markdown level1 summary"><p>The machine-coordinate axes <code class="paramref">chain</code> actually has: an
axis counts when a transformer is bound to its name
(<a class="xref" href="Hi.Numerical.Xyzabc.IXyzabcChain.html#Hi_Numerical_Xyzabc_IXyzabcChain_GetTransformerX">GetTransformerX()</a>
<a class="xref" href="Hi.Numerical.Xyzabc.IXyzabcChain.html#Hi_Numerical_Xyzabc_IXyzabcChain_GetTransformerC">GetTransformerC()</a>). A three-axis chain yields
X, Y, Z only; a null chain yields nothing.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static List&lt;string&gt; GetChainAxisNames(IXyzabcChain chain, bool linearOnly = false)</code></pre>
</div>
<h4 class="section">Parameters</h4>
<dl class="parameters">
<dt><code>chain</code> <a class="xref" href="Hi.Numerical.Xyzabc.IXyzabcChain.html">IXyzabcChain</a></dt>
<dd><p>The machine chain, or null.</p>
</dd>
<dt><code>linearOnly</code> <a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd><p>When true, only the translation axes (X, Y, Z) are returned. A travel
audit wants this: a linear axis always has a finite travel, so a
missing limit is unambiguously a gap, while a rotary table that turns
continuously legitimately has none and cannot be given one.</p>
</dd>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.collections.generic.list-1">List</a>&lt;<a class="xref" href="https://learn.microsoft.com/dotnet/api/system.string">string</a>&gt;</dt>
<dd></dd>
</dl>
</article>
<div class="contribution d-print-none">
</div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<span> Copyright © 2025 <a href='https://superhightech.com.tw'>Tech Coordinate</a>. All rights reserved. <a href='https://superhightech.com.tw'>超級高科技股份有限公司</a> © 2025 版權所有 </span>
</div>
</div>
</footer>
</body>
</html>
@@ -164,6 +164,18 @@ Stored per machine in
consumed by <a class="xref" href="Hi.NcParsers.LogicSyntaxs.MCodeExpansionSyntax.html">MCodeExpansionSyntax</a>, which
expands the declared code into the canonical ISO flags the regular
consumers already understand.</p>
</dd>
</dl>
<dl class="jumplist">
<dt><a class="xref" href="Hi.NcParsers.Dependencys.StrokeLimitUtil.html">StrokeLimitUtil</a></dt>
<dd><p>Load-time audit helpers for <a class="xref" href="Hi.NcParsers.Dependencys.IStrokeLimitConfig.html">IStrokeLimitConfig</a>: which
machine-coordinate axes the chain has, and which of them the stroke limit
check cannot judge because no limit is configured. Both checks — the
per-block <a class="xref" href="Hi.NcParsers.Semantics.StrokeLimitCheckSemantic.html">StrokeLimitCheckSemantic</a> and the per-step
<a class="xref" href="Hi.NcParsers.Dependencys.IStrokeLimitConfig.html#Hi_NcParsers_Dependencys_IStrokeLimitConfig_CheckStrokeLimit_Hi_Geom_DVec3d_System_IProgress_Hi_Common_Messages_IMessage__">CheckStrokeLimit(DVec3d, IProgress&lt;IMessage&gt;)</a> — compare only axes that
carry a limit, so a machine file without limits passes every position
silently while <code>EnableStrokeLimitCheck</code> reads as on. The session
begin reports that gap once through these helpers.</p>
</dd>
</dl>
<h3 id="interfaces">
@@ -253,6 +253,31 @@ G98/G99 flag on the same block):
<pre><code class="lang-csharp">{ "Parsing": { "Flags": ["G80"] } }</code></pre>
<p>#AfterBuild:</p>
<pre><code class="lang-csharp">{ "CannedCycle": { "Term": "G80" } }</code></pre>
<p>The first block after a program end — <code>#Previous:</code> carries the
<code>ProgramEnd</code> section next to a still-active G81, and the block
itself has an X word that would have repeated the cycle. This is the
reset edge (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.html">ProgramEndSyntax</a>): the controller's reset
cancels the canned cycle, so no repeat is resolved (the X word stays
for the positioning syntaxes) and the G80 sentinel is written
explicitly — an authored section, so the modal carry does not clone
the active cycle across the edge. No <code>ReturnMode</code>: the G98
default applies after reset:
#Previous:</p>
<pre><code class="lang-csharp">{
"ProgramEnd": { "Term": "M30" },
"CannedCycle": {
"Term": "G81",
"ReturnMode": "G99",
"Params": { "X": 50, "Y": 30, "Z": -10, "R": 2 }
}
}</code></pre>
<p>#BeforeBuild:</p>
<pre><code class="lang-csharp">{ "Parsing": { "X": 60 } }</code></pre>
<p>#AfterBuild:</p>
<pre><code class="lang-csharp">{
"Parsing": { "X": 60 },
"CannedCycle": { "Term": "G80" }
}</code></pre>
@@ -353,6 +353,36 @@ flag (no parameter object to hang an H on):
}
]
}</code></pre>
The first block after a program end — <code>#Previous:</code> carries the
<code>ProgramEnd</code> section next to the still-active G43.4, and the
block itself swings a rotary axis (as a post-M02 <code>G0 A90.</code> does
when a CAM file chains several programs). This is the reset edge
(<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.html">ProgramEndSyntax</a>): the controller's reset cancels
tool-center-point control, so the modal is <b>not</b> carried, no
<code>Dynamic</code> entry is written (the swing stays a plain McLinear
rotary move instead of pinning the tool tip), and the block gets the
G49 sentinel with the identity Mat4d — <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ToolHeightOffsetSyntax.html">ToolHeightOffsetSyntax</a>
skipped this block because the previous term was not ISO:
#Previous:
<pre><code class="lang-csharp">{
"ProgramEnd": { "Term": "M02" },
"MachineCoordinateState": { "X": 0, "Y": 0, "Z": 0, "A": 0, "B": 0 },
"ToolHeightCompensation": { "Offset_mm": 10, "Term": "G43.4", "OffsetId": 1 }
}</code></pre>
#BeforeBuild:
<pre><code class="lang-csharp">{ "MachineCoordinateState": { "A": 90, "B": 0 } }</code></pre>
#AfterBuild:
<pre><code class="lang-csharp">{
"MachineCoordinateState": { "A": 90, "B": 0 },
"ToolHeightCompensation": { "Offset_mm": 0, "Term": "G49", "OffsetId": 0 },
"ProgramToMcTransform": [
{
"Source": "ToolHeightCompensation",
"Kind": "Static",
"Mat4d": [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]
}
]
}</code></pre>
@@ -324,6 +324,35 @@ identity:
}
]
}</code></pre>
<p>The first block after a program end — <code>#Previous:</code> carries the
<code>ProgramEnd</code> section (<code>END PGM</code>, M2 or M30) next to the
still-active M128. This is the reset edge
(<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.html">ProgramEndSyntax</a>): the TNC resets M128 / FUNCTION
TCPM at program end while the TOOL CALL length compensation stays,
so the block gets exactly the M129 hand-back:
#Previous:</p>
<pre><code class="lang-csharp">{
"ProgramEnd": { "Term": "END PGM" },
"ToolHeightCompensation": {
"Offset_mm": 120.5, "Term": "M128", "OffsetId": 2,
"PriorTerm": "TOOL CALL", "Delta_mm": 0.5, "FeedLimit": 6000
}
}</code></pre>
<p>#BeforeBuild:</p>
<pre><code class="lang-csharp">{}</code></pre>
<p>#AfterBuild:</p>
<pre><code class="lang-csharp">{
"ToolHeightCompensation": {
"Offset_mm": 120.5, "Term": "TOOL CALL", "OffsetId": 2, "Delta_mm": 0.5
},
"ProgramToMcTransform": [
{
"Source": "ToolHeightCompensation",
"Kind": "Static",
"Mat4d": [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,120.5,1]
}
]
}</code></pre>
@@ -319,6 +319,32 @@ The <a class="xref" href="Hi.NcParsers.Keywords.TiltTransform.html">TiltTransfor
}
]
}</code></pre>
The first block after a program end — <code>#Previous:</code> carries the
<code>ProgramEnd</code> section next to the still-active G68.2. This is the
reset edge (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.html">ProgramEndSyntax</a>): the controller's reset
cancels the tilted work plane, so
<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> does not
carry the tilt and writes the explicit G69 cancel state instead (the
same shape as case 0), leaving the unrelated G00 flag alone:
#Previous:
<pre><code class="lang-csharp">{
"ProgramEnd": { "Term": "M30" },
"TiltTransform": { "Term": "G68.2", "X": 0, "Y": 0, "Z": 0, "I": 0, "J": 30, "K": 0 }
}</code></pre>
#BeforeBuild:
<pre><code class="lang-csharp">{ "Parsing": { "Flags": ["G00"] } }</code></pre>
#AfterBuild:
<pre><code class="lang-csharp">{
"Parsing": { "Flags": ["G00"] },
"TiltTransform": { "Term": "G69" },
"ProgramToMcTransform": [
{
"Source": "TiltTransform",
"Kind": "Static",
"Mat4d": [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]
}
]
}</code></pre>
<h2 id="Hi_NcParsers_LogicSyntaxs_IsoG68p2TiltSyntax_remarks">Remarks</h2>
@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class MachineCoordSelectSyntax | HiAPI-C# 2025 ">
<meta name="description" content="Handles machine coordinate selection — non-modal, one-shot. The axis values (X/Y/Z) in the block are interpreted as machine coordinates, bypassing all work offsets, local coordinates, tool height compensation, and coordinate rotations. If G91 (incremental) is active, the code is ignored per ISO standard. A per-word incremental stamp on the block (block-root entry — Siemens SUPA Y=IC(-10), klartext L IY-10 M91) is a distance in the machine frame: the word is added to the previous machine position of that axis. Defaults to ISO G53. Brands with additional one-shot machine-coordinate codes widen — the Siemens preset adds G153 and SUPA (both suppress every active frame for one block; in this pipeline all of those reduce to &quot;bypass the composed &quot;, which the ProgramXyz back-derivation below already models). The matched code is stamped verbatim into for bidirectional source recovery. Rotary words on the same block (e.g. SUPA G0 B0) are left to — same behavior as ISO G53, where rotary axes flow through the normal rotary path. Must be placed before and in the syntax chain. When a supported code is active, this syntax consumes X/Y/Z from and writes directly, preventing from processing them as program coordinates — and, ahead of the resolve, reading a per-word incremental word raw instead of re-based into the program frame.">
<meta name="description" content="Handles machine coordinate selection — non-modal, one-shot. The axis values (X/Y/Z) in the block are interpreted as machine coordinates, bypassing all work offsets, local coordinates, tool height compensation, and coordinate rotations. If G91 (incremental) is active, the code is ignored per ISO standard. A per-word incremental stamp on the block (block-root entry — Siemens SUPA Y=IC(-10), klartext L IY-10 M91) is a distance in the machine frame: the word is added to the previous machine position of that axis. Defaults to ISO G53. Brands with additional one-shot machine-coordinate codes widen — the Siemens preset adds G153 and SUPA (both suppress every active frame for one block; in this pipeline all of those reduce to &quot;bypass the composed &quot;, which the ProgramXyz back-derivation below already models). The matched code is stamped verbatim into for bidirectional source recovery. Rotary words on the same block (e.g. SUPA G0 B0, G53 A0 C0) are consumed by ahead of this syntax — machine and program rotary coincide while no rotary offsets are modeled — and the block is still a machine-coordinate positioning: the linear axes hold their machine position when no X/Y/Z word is given, and the motion is always . A machine-coordinate block never takes the RTCP tool-center-point linkage: on a real controller G53 applies no compensation, so a rotary swing commanded through it turns the axis in place instead of dragging X/Y/Z to pin the tool tip (the tip&#39;s post-swing program coordinate is what the back-derivation reports). Must be placed before and in the syntax chain. When a supported code is active, this syntax consumes X/Y/Z from and writes directly, preventing from processing them as program coordinates — and, ahead of the resolve, reading a per-word incremental word raw instead of re-based into the program frame.">
<link rel="icon" href="../img/HiAPI.favicon.ico">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
@@ -116,9 +116,18 @@ active frame for one block; in this pipeline all of those reduce to
which the ProgramXyz back-derivation below already models). The
matched code is stamped verbatim into
<a class="xref" href="Hi.NcParsers.Keywords.IMotionEventDef.html#Hi_NcParsers_Keywords_IMotionEventDef_Term">Term</a> for bidirectional source recovery.
Rotary words on the same block (e.g. <code>SUPA G0 B0</code>) are left to
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a> — same behavior as ISO G53, where rotary
axes flow through the normal rotary path.
Rotary words on the same block (e.g. <code>SUPA G0 B0</code>,
<code>G53 A0 C0</code>) are consumed by <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a> ahead of
this syntax — machine and program rotary coincide while no rotary
offsets are modeled — and the block is still a machine-coordinate
positioning: the linear axes <b>hold their machine position</b>
when no X/Y/Z word is given, and the motion is always
<a class="xref" href="Hi.NcParsers.Keywords.Generic.MotionForm.html#Hi_NcParsers_Keywords_Generic_MotionForm_McLinear">McLinear</a>. A machine-coordinate block never
takes the RTCP tool-center-point linkage: on a real controller G53
applies no compensation, so a rotary swing commanded through it
turns the axis in place instead of dragging X/Y/Z to pin the tool
tip (the tip's post-swing program coordinate is what the
back-derivation reports).
</p>
<p>
Must be placed <b>before</b> <a class="xref" href="Hi.NcParsers.LogicSyntaxs.IncrementalResolveSyntax.html">IncrementalResolveSyntax</a>
@@ -301,6 +310,44 @@ section stays on the block (one-shot, nobody consumes it):
"ProgramXyz": { "X": 100, "Y": 40, "Z": -200 },
"MotionEvent": { "Form": "McLinear", "IsRapid": true, "Term": "G53" }
}</code></pre>
<p>Rotary-only machine-coordinate block under RTCP (<code>G0 G53 A0.</code>
while <code>G43.4</code> is active) — <code>McAbcSyntax</code> has already
consumed the rotary word into <code>MachineCoordinateState</code>, and
<code>G43p4RtcpSyntax</code> has tagged the chain <code>Dynamic</code> because
the tool orientation changes across the block. The linear axes hold
the previous machine position (G53 applies no compensation, so the
swing turns the axis in place instead of pinning the tool tip) and
the motion is stamped <code>McLinear</code>; <code>ProgramXyz</code> is the tip's
program coordinate after the swing — the 10 mm tool-height entry is
inverted, MC Z 0 → program Z 10:
#Previous:</p>
<pre><code class="lang-csharp">{ "MachineCoordinateState": { "X": -1, "Y": -1, "Z": 0, "A": 90 } }</code></pre>
<p>#BeforeBuild:</p>
<pre><code class="lang-csharp">{
"Parsing": { "Flags": ["G53", "G00"] },
"MachineCoordinateState": { "A": 0 },
"ProgramToMcTransform": [
{
"Source": "ToolHeightCompensation",
"Kind": "Dynamic",
"Mat4d": [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,10,1]
}
]
}</code></pre>
<p>#AfterBuild:</p>
<pre><code class="lang-csharp">{
"MachineCoordinateState": { "A": 0, "X": -1, "Y": -1, "Z": 0 },
"ProgramToMcTransform": [
{
"Source": "ToolHeightCompensation",
"Kind": "Dynamic",
"Mat4d": [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,10,1]
}
],
"ProgramXyz": { "X": -1, "Y": -1, "Z": -10 },
"MotionState": { "Term": "G00" },
"MotionEvent": { "Form": "McLinear", "IsRapid": true, "Term": "G53" }
}</code></pre>
@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Class ProgramEndSyntax | HiAPI-C# 2025 ">
<meta name="description" content="Consumes M02/M30 (program end) from and writes section. Downstream syntaxes that need to reset modal state on program end (e.g. for G52 reset) should read the section rather than scanning for M30 in Flags directly. Must be placed before syntaxes that depend on the ProgramEnd section.">
<meta name="description" content="Consumes M02/M30 (program end) from and writes section. Downstream syntaxes that need to reset modal state on program end (e.g. for G52 reset) should read the section rather than scanning for M30 in Flags directly. The program-end edge. On a real controller M02/M30 ends the program and enters the reset state: the modal G codes return to their power-on defaults — tool length compensation is cancelled (G49, which also ends tool-center-point control: Fanuc TCP is cancelled by G49 or reset), the tilted work plane and coordinate rotation are cancelled (G69), cutter radius compensation is cancelled (G40), the canned cycle is cancelled (G80). A simulator that plays a file with several programs chained by M02 must keep playing, so the reset is modelled as an edge between the program-end block and its successor: the program-end block itself keeps the modal state it executed under (its own motion — G0 Z100. M30 — still sees the compensation), and the successor starts from the reset defaults. Each modal owner tests the edge with in its single-step node.Previous lookback and writes its cancel state on the successor instead of carrying: (G43/G44 → G49), (G43.4 → G49), (TRAORI → TRAFOOF, the D compensation itself stays — Siemens retains the active tool on reset), (M128 / TCPM → off, TOOL CALL compensation stays), (every tilt / rotation / frame term → G69), (G41/G42 → G40, the modal D is kept) and (→ G80). Deliberately not reset: G00/G01, G90/G91, G17G19, G94/G95, the work offset (G54G59) and the path-smoothing mode — their reset defaults are controller-parameter dependent and they do not enter the program→machine transform chain; G20/G21 is retained by the controller itself. G52 keeps its existing behaviour of clearing on the program-end block (HardNc parity). A block right after the edge that has no words at all (a comment line) is still the edge — every owner handles it before any &quot;no Parsing&quot; early return, or the modal carry would clone the active section across it. Must be placed before syntaxes that depend on the ProgramEnd section.">
<link rel="icon" href="../img/HiAPI.favicon.ico">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
@@ -105,6 +105,40 @@ Downstream syntaxes that need to reset modal state on program end
should read the <a class="xref" href="Hi.NcParsers.Keywords.ProgramEnd.html">ProgramEnd</a> section rather than
scanning for M30 in Flags directly.
</p>
<p>
<b>The program-end edge.</b> On a real controller M02/M30 ends the
program and enters the reset state: the modal G codes return to their
power-on defaults — tool length compensation is cancelled (G49, which
also ends tool-center-point control: Fanuc TCP is cancelled by G49 or
reset), the tilted work plane and coordinate rotation are cancelled
(G69), cutter radius compensation is cancelled (G40), the canned cycle
is cancelled (G80). A simulator that plays a file with several
programs chained by M02 must keep playing, so the reset is modelled as
an <i>edge</i> between the program-end block and its successor: the
program-end block itself keeps the modal state it executed under (its
own motion — <code>G0 Z100. M30</code> — still sees the compensation), and
the successor starts from the reset defaults. Each modal owner tests
the edge with <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.html#Hi_NcParsers_LogicSyntaxs_ProgramEndSyntax_IsResetEdge_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__">IsResetEdge(LazyLinkedListNode&lt;SyntaxPiece&gt;)</a> in its single-step
<code>node.Previous</code> lookback and writes its cancel state on the
successor instead of carrying: <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ToolHeightOffsetSyntax.html">ToolHeightOffsetSyntax</a>
(G43/G44 → G49), <a class="xref" href="Hi.NcParsers.LogicSyntaxs.G43p4RtcpSyntax.html">G43p4RtcpSyntax</a> (G43.4 → G49),
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Siemens.SiemensTraoriSyntax.html">SiemensTraoriSyntax</a> (TRAORI → TRAFOOF, the
D compensation itself stays — Siemens retains the active tool on
reset), <a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainRtcpSyntax.html">HeidenhainRtcpSyntax</a> (M128 / TCPM
→ off, TOOL CALL compensation stays), <a class="xref" href="Hi.NcParsers.LogicSyntaxs.TiltTransformUtil.html">TiltTransformUtil</a>
(every tilt / rotation / frame term → G69),
<a class="xref" href="Hi.NcParsers.PostLogicSyntaxs.RadiusCompensationSyntax.html">RadiusCompensationSyntax</a> (G41/G42 →
G40, the modal D is kept) and <a class="xref" href="Hi.NcParsers.LogicSyntaxs.CannedCycleResolveSyntax.html">CannedCycleResolveSyntax</a>
(→ G80). Deliberately not reset: G00/G01, G90/G91, G17G19, G94/G95,
the work offset (G54G59) and the path-smoothing mode — their reset
defaults are controller-parameter dependent and they do not enter the
program→machine transform chain; G20/G21 is retained by the controller
itself. G52 keeps its existing behaviour of clearing on the
program-end block (HardNc parity). A block right after the edge that
has no words at all (a comment line) is still the edge — every owner
handles it before any "no Parsing" early return, or the modal carry
would clone the active section across it.
</p>
Must be placed before syntaxes that depend on the ProgramEnd section.
</div>
<div class="markdown conceptual"></div>
@@ -377,6 +411,51 @@ Must be placed before syntaxes that depend on the ProgramEnd section.
<a id="Hi_NcParsers_LogicSyntaxs_ProgramEndSyntax_IsResetEdge_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.IsResetEdge*"></a>
<h3 id="Hi_NcParsers_LogicSyntaxs_ProgramEndSyntax_IsResetEdge_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.IsResetEdge(Hi.Common.Collections.LazyLinkedListNode{Hi.NcParsers.Syntaxs.SyntaxPiece})">
IsResetEdge(LazyLinkedListNode&lt;SyntaxPiece&gt;)
</h3>
<div class="markdown level1 summary"><p>True when <code class="paramref">node</code> is the first block after a
program end — its predecessor carries the <a class="xref" href="Hi.NcParsers.Keywords.ProgramEnd.html">ProgramEnd</a>
section (M02 / M30, or a brand equivalent such as klartext
<code>END PGM</code>). Modal owners call this in their
<code>node.Previous</code> lookback and, when true, write their reset
(cancel) state on <code class="paramref">node</code> instead of carrying the
predecessor's modal forward — see the class summary for the set.
The section is one-shot (never carried), so the edge is exactly one
block wide.</p>
</div>
<div class="markdown level1 conceptual"></div>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public static bool IsResetEdge(LazyLinkedListNode&lt;SyntaxPiece&gt; node)</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>
</dl>
<h4 class="section">Returns</h4>
<dl class="parameters">
<dt><a class="xref" href="https://learn.microsoft.com/dotnet/api/system.boolean">bool</a></dt>
<dd></dd>
</dl>
<a id="Hi_NcParsers_LogicSyntaxs_ProgramEndSyntax_MakeXmlSource_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.MakeXmlSource*"></a>
<h3 id="Hi_NcParsers_LogicSyntaxs_ProgramEndSyntax_MakeXmlSource_System_String_System_String_System_Boolean_" data-uid="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.MakeXmlSource(System.String,System.String,System.Boolean)">
@@ -309,6 +309,33 @@ consumed silently, nothing written:
<pre><code class="lang-csharp">{ "Parsing": { "Flags": ["TRAFOOF"] } }</code></pre>
<p>#AfterBuild:</p>
<pre><code class="lang-csharp">{}</code></pre>
<p>The first block after a program end — <code>#Previous:</code> carries the
<code>ProgramEnd</code> section next to the still-active TRAORI. This is
the reset edge (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.html">ProgramEndSyntax</a>): the control's reset
deactivates the transformation (the MD20110 default is TRAFOOF on
reset) while the tool's D compensation stays active, so the block
gets exactly the TRAFOOF hand-back — the section returns to the
recorded owner with the plain translation entry:
#Previous:</p>
<pre><code class="lang-csharp">{
"ProgramEnd": { "Term": "M30" },
"ToolHeightCompensation": {
"Offset_mm": 50, "Term": "TRAORI", "OffsetId": 2, "PriorTerm": "D"
}
}</code></pre>
<p>#BeforeBuild:</p>
<pre><code class="lang-csharp">{}</code></pre>
<p>#AfterBuild:</p>
<pre><code class="lang-csharp">{
"ToolHeightCompensation": { "Offset_mm": 50, "Term": "D", "OffsetId": 2 },
"ProgramToMcTransform": [
{
"Source": "ToolHeightCompensation",
"Kind": "Static",
"Mat4d": [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,50,1]
}
]
}</code></pre>
@@ -201,6 +201,16 @@ tilt rotation into <a class="xref" href="Hi.NcParsers.Keywords.ITransformationDe
<div class="markdown level1 summary"><p>Carries forward the tilt transform from a previous node
when the current block has no new tilt command.
Shared by all tilt syntaxes (G68, G68.2, CYCLE800, PLANE SPATIAL).</p>
<p>
At the program-end edge (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.html#Hi_NcParsers_LogicSyntaxs_ProgramEndSyntax_IsResetEdge_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__">IsResetEdge(LazyLinkedListNode&lt;SyntaxPiece&gt;)</a>
— the previous block carried M02 / M30 / <code>END PGM</code>) an active
term is <b>not</b> carried: the controller's reset cancels the tilted
work plane, the coordinate rotation and the programmable frames, so
the successor gets the explicit cancel state (<code>G69</code> section +
identity entry, the shape <a class="xref" href="Hi.NcParsers.LogicSyntaxs.TiltTransformUtil.html#Hi_NcParsers_LogicSyntaxs_TiltTransformUtil_TryHandleG69_System_Text_Json_Nodes_JsonObject_System_Text_Json_Nodes_JsonObject_">TryHandleG69(JsonObject, JsonObject)</a> writes) — an
explicit section, so <a class="xref" href="Hi.NcParsers.PostLogicSyntaxs.ModalCarrySyntax.html">ModalCarrySyntax</a>
does not clone the predecessor's active section onto it.
</p>
</div>
<div class="markdown level1 conceptual"></div>
@@ -300,6 +300,35 @@ and the same offset-1 table provides 99.98 mm:
}
]
}</code></pre>
The first block after a program end — <code>#Previous:</code> carries the
<code>ProgramEnd</code> section next to the still-active G43 H1. This is
the reset edge (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.html">ProgramEndSyntax</a>): the controller's
reset cancels tool length compensation, so the modal is not carried
and the block gets the same G49 sentinel and identity Mat4d an
explicit G49 writes; the unrelated G00 flag survives:
#Previous:
<pre><code class="lang-csharp">{
"ProgramEnd": { "Term": "M30" },
"ToolHeightCompensation": {
"Offset_mm": 99.98, "Term": "G43", "OffsetId": 1
}
}</code></pre>
#BeforeBuild:
<pre><code class="lang-csharp">{ "Parsing": { "Flags": ["G00"] } }</code></pre>
#AfterBuild:
<pre><code class="lang-csharp">{
"Parsing": { "Flags": ["G00"] },
"ToolHeightCompensation": {
"Offset_mm": 0, "Term": "G49", "OffsetId": 0
},
"ProgramToMcTransform": [
{
"Source": "ToolHeightCompensation",
"Kind": "Static",
"Mat4d": [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]
}
]
}</code></pre>
<h2 id="Hi_NcParsers_LogicSyntaxs_ToolHeightOffsetSyntax_remarks">Remarks</h2>
@@ -655,9 +655,18 @@ active frame for one block; in this pipeline all of those reduce to
which the ProgramXyz back-derivation below already models). The
matched code is stamped verbatim into
<a class="xref" href="Hi.NcParsers.Keywords.IMotionEventDef.html#Hi_NcParsers_Keywords_IMotionEventDef_Term">Term</a> for bidirectional source recovery.
Rotary words on the same block (e.g. <code>SUPA G0 B0</code>) are left to
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a> — same behavior as ISO G53, where rotary
axes flow through the normal rotary path.
Rotary words on the same block (e.g. <code>SUPA G0 B0</code>,
<code>G53 A0 C0</code>) are consumed by <a class="xref" href="Hi.NcParsers.LogicSyntaxs.McAbcSyntax.html">McAbcSyntax</a> ahead of
this syntax — machine and program rotary coincide while no rotary
offsets are modeled — and the block is still a machine-coordinate
positioning: the linear axes <b>hold their machine position</b>
when no X/Y/Z word is given, and the motion is always
<a class="xref" href="Hi.NcParsers.Keywords.Generic.MotionForm.html#Hi_NcParsers_Keywords_Generic_MotionForm_McLinear">McLinear</a>. A machine-coordinate block never
takes the RTCP tool-center-point linkage: on a real controller G53
applies no compensation, so a rotary swing commanded through it
turns the axis in place instead of dragging X/Y/Z to pin the tool
tip (the tip's post-swing program coordinate is what the
back-derivation reports).
</p>
<p>
Must be placed <b>before</b> <a class="xref" href="Hi.NcParsers.LogicSyntaxs.IncrementalResolveSyntax.html">IncrementalResolveSyntax</a>
@@ -1138,6 +1147,40 @@ Downstream syntaxes that need to reset modal state on program end
should read the <a class="xref" href="Hi.NcParsers.Keywords.ProgramEnd.html">ProgramEnd</a> section rather than
scanning for M30 in Flags directly.
</p>
<p>
<b>The program-end edge.</b> On a real controller M02/M30 ends the
program and enters the reset state: the modal G codes return to their
power-on defaults — tool length compensation is cancelled (G49, which
also ends tool-center-point control: Fanuc TCP is cancelled by G49 or
reset), the tilted work plane and coordinate rotation are cancelled
(G69), cutter radius compensation is cancelled (G40), the canned cycle
is cancelled (G80). A simulator that plays a file with several
programs chained by M02 must keep playing, so the reset is modelled as
an <i>edge</i> between the program-end block and its successor: the
program-end block itself keeps the modal state it executed under (its
own motion — <code>G0 Z100. M30</code> — still sees the compensation), and
the successor starts from the reset defaults. Each modal owner tests
the edge with <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.html#Hi_NcParsers_LogicSyntaxs_ProgramEndSyntax_IsResetEdge_Hi_Common_Collections_LazyLinkedListNode_Hi_NcParsers_Syntaxs_SyntaxPiece__">IsResetEdge(LazyLinkedListNode&lt;SyntaxPiece&gt;)</a> in its single-step
<code>node.Previous</code> lookback and writes its cancel state on the
successor instead of carrying: <a class="xref" href="Hi.NcParsers.LogicSyntaxs.ToolHeightOffsetSyntax.html">ToolHeightOffsetSyntax</a>
(G43/G44 → G49), <a class="xref" href="Hi.NcParsers.LogicSyntaxs.G43p4RtcpSyntax.html">G43p4RtcpSyntax</a> (G43.4 → G49),
<a class="xref" href="Hi.NcParsers.LogicSyntaxs.Siemens.SiemensTraoriSyntax.html">SiemensTraoriSyntax</a> (TRAORI → TRAFOOF, the
D compensation itself stays — Siemens retains the active tool on
reset), <a class="xref" href="Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainRtcpSyntax.html">HeidenhainRtcpSyntax</a> (M128 / TCPM
→ off, TOOL CALL compensation stays), <a class="xref" href="Hi.NcParsers.LogicSyntaxs.TiltTransformUtil.html">TiltTransformUtil</a>
(every tilt / rotation / frame term → G69),
<a class="xref" href="Hi.NcParsers.PostLogicSyntaxs.RadiusCompensationSyntax.html">RadiusCompensationSyntax</a> (G41/G42 →
G40, the modal D is kept) and <a class="xref" href="Hi.NcParsers.LogicSyntaxs.CannedCycleResolveSyntax.html">CannedCycleResolveSyntax</a>
(→ G80). Deliberately not reset: G00/G01, G90/G91, G17G19, G94/G95,
the work offset (G54G59) and the path-smoothing mode — their reset
defaults are controller-parameter dependent and they do not enter the
program→machine transform chain; G20/G21 is retained by the controller
itself. G52 keeps its existing behaviour of clearing on the
program-end block (HardNc parity). A block right after the edge that
has no words at all (a comment line) is still the edge — every owner
handles it before any "no Parsing" early return, or the modal carry
would clone the active section across it.
</p>
Must be placed before syntaxes that depend on the ProgramEnd section.
</dd>
</dl>
@@ -273,6 +273,21 @@ the modal fallthrough, not real motion, so it counts as bare:
"MotionEvent": { "Form": "McLinear" },
"RadiusCompensation": { "Side": "None", "Term": "G40", "OffsetId": 1 }
}</code></pre>
<p>The first block after a program end — <code>#Previous:</code> carries the
<code>ProgramEnd</code> section next to a still-active G41 D1. This is the
reset edge (<a class="xref" href="Hi.NcParsers.LogicSyntaxs.ProgramEndSyntax.html">ProgramEndSyntax</a>): the
controller's reset cancels cutter compensation, so the block is
written cancelled (G40) instead of inheriting G41; the modal D row
is kept, as it is across an explicit G40:
#Previous:</p>
<pre><code class="lang-csharp">{
"ProgramEnd": { "Term": "M02" },
"RadiusCompensation": { "Side": "Left", "Term": "G41", "OffsetId": 1, "Radius_mm": 5 }
}</code></pre>
<p>#BeforeBuild:</p>
<pre><code class="lang-csharp">{}</code></pre>
<p>#AfterBuild:</p>
<pre><code class="lang-csharp">{ "RadiusCompensation": { "Side": "None", "Term": "G40", "OffsetId": 1 } }</code></pre>
+3
View File
@@ -2528,6 +2528,9 @@
<li>
<a href="Hi.NcParsers.Dependencys.MCodeEffects.html" name="" title="MCodeEffects">MCodeEffects</a>
</li>
<li>
<a href="Hi.NcParsers.Dependencys.StrokeLimitUtil.html" name="" title="StrokeLimitUtil">StrokeLimitUtil</a>
</li>
</ul>
</li>
<li>
File diff suppressed because one or more lines are too long