Archived
1408 lines
118 KiB
HTML
1408 lines
118 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>Upgrading from 3.1.175 to 3.2 | HiAPI-C# 2025 </title>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="title" content="Upgrading from 3.1.175 to 3.2 | HiAPI-C# 2025 ">
|
||
|
||
|
||
<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 "{query}"">
|
||
<meta name="loc:searchNoResults" content="No results for "{query}"">
|
||
<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="">
|
||
<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="Release-Upgrading-To-3.2">
|
||
<h1 id="upgrading-from-31175-to-32">Upgrading from 3.1.175 to 3.2</h1>
|
||
|
||
<p>This page is the long form of the <a href="index.html">3.2 release-note entry</a>. It exists because 3.2 is not
|
||
an increment on the last release most callers hold — it is the accumulation of everything that
|
||
landed after the 3.1.175 package set, delivered in one step.</p>
|
||
<p>Read it in order the first time. The two sections that decide whether an upgrade is a recompile or
|
||
an afternoon are <a href="#breaking-changes">Breaking changes</a> and
|
||
<a href="#results-that-change-on-upgrade">Results that change on upgrade</a>; everything after them is new
|
||
capability you can adopt when you need it.</p>
|
||
<div class="IMPORTANT">
|
||
<h5>Important</h5>
|
||
<p>Read the <strong>Adoption status</strong> note on the <a href="index.html">release-note page</a> before planning around this.
|
||
The short version: 3.2 is published for review, verification is still in progress across most
|
||
areas, and <strong>NC optimization is not finished on this line</strong> — work that depends on it should stay
|
||
on 3.1, serviced as <code>3.1.175.<patch></code>.</p>
|
||
</div>
|
||
<h2 id="the-package-line">The package line</h2>
|
||
<p><code>master</code> develops the <strong>3.2</strong> package line as of 2026-08-19. All ten packages — HiGeom, HiLicense,
|
||
HiDisp, Hi.WinForm, Hi.WpfPlus, HiCbtr, HiMech, HiUniNc, HiNc, HiNc-Resource — moved to 3.2
|
||
together and <strong>restarted their build counters</strong>.</p>
|
||
<p>Three consequences worth stating plainly:</p>
|
||
<ul>
|
||
<li>A 3.2 build number starts low. <code>3.2.6</code> is <em>newer</em> than <code>3.1.204</code>; the two counters are not
|
||
comparable, and the gap between the last 3.1 number a feed served and the first 3.2 number is
|
||
expected rather than a missing upload.</li>
|
||
<li>The <strong>3.1 line is closed at the 3.1.175 set</strong> and is serviced only as <code>3.1.175.<patch></code>. A
|
||
reference left on 3.1.175.x receives correctness fixes for that line and none of the capability
|
||
on this page.</li>
|
||
<li>The versions between — 3.1.176 through 3.1.204 — were never published as a release set. That is
|
||
why the release note carries one 3.2 entry where it might have carried a dozen: for a caller
|
||
moving off 3.1.175, they were never separate releases.</li>
|
||
</ul>
|
||
<h2 id="breaking-changes">Breaking changes</h2>
|
||
<p>In the order they will bite an upgrading host.</p>
|
||
<h3 id="1-registration-before-anything-else">1. Registration, before anything else</h3>
|
||
<p><code>XFactory.Generators</code> changes from a plain <code>Dictionary</code> to a <code>ConcurrentDictionary</code>, so parallel
|
||
<code>Reg()</code> calls no longer corrupt the registration map. The property is public, so a caller that
|
||
declares its type explicitly stops compiling.</p>
|
||
<p>Carried over from 3.1.172 and still the first thing an upgrading host hits:
|
||
<a class="xref" href="../api/Hi.MachiningProcs.LocalProjectService.html#Hi_MachiningProcs_LocalProjectService_Reg_">Reg</a> must be called once at startup, <strong>before any
|
||
project XML is deserialized</strong>. Registration no longer happens by accident when a type is first
|
||
touched. See <a href="../fundamentals/common/xml-io.html">XML IO</a>.</p>
|
||
<h3 id="2-the-message-channel">2. The message channel</h3>
|
||
<p>Message reporting is rebuilt on a unified model. Every notification carries a
|
||
<a class="xref" href="../api/Hi.Common.Messages.Severity.html">Severity</a>, a <a class="xref" href="../api/Hi.Common.Messages.Category.html">Category</a> and a filterable id
|
||
(<a class="xref" href="../api/Hi.Common.Messages.SimpleMessage.html">SimpleMessage</a>), and arrives on one of three <strong>typed sinks</strong>:
|
||
<a class="xref" href="../api/Hi.MachiningProcs.ShellProgress.html">ShellProgress</a> for session-lifecycle messages,
|
||
<a class="xref" href="../api/Hi.MachiningProcs.StepDiagnosticProgress.html">StepDiagnosticProgress</a> for step-anchored diagnostics, and
|
||
<a class="xref" href="../api/Hi.NcParsers.NcDiagnosticProgress.html">NcDiagnosticProgress</a> for NC-parsing diagnostics.</p>
|
||
<p><code>MixedProgress0</code>, <code>MultiTagMessage</code> and <code>MultiTagMessageUtil</code> are removed. Every message parameter
|
||
across the API — the <a class="xref" href="../api/Hi.Common.XmlUtils.XFactory.html">XFactory</a> deserialization chain included — is retyped
|
||
from <code>IProgress<object></code> to <code>IProgress<IMessage></code>. <code>Category.General</code> is deleted,
|
||
<a class="xref" href="../api/Hi.Common.Messages.MessageUtil.html">MessageUtil</a> becomes id-first <code>{Category}{Severity}</code>, and
|
||
<code>NcDiagnostic.Text</code> renames to <a class="xref" href="../api/Hi.NcParsers.NcDiagnostic.html#Hi_NcParsers_NcDiagnostic_Notification">Notification</a>. See
|
||
<a href="../fundamentals/common/message-management.html">Message Management</a>.</p>
|
||
<h3 id="3-the-session-surface">3. The session surface</h3>
|
||
<p><code>LocalProjectService.SessionShell</code> is created by <code>BeginSession()</code> and nulled at <code>EndSession()</code> — it
|
||
is <strong>null outside a session</strong> and no longer lazily created. <a class="xref" href="../api/Hi.MachiningProcs.ShellProgress.html">ShellProgress</a>
|
||
is recreated per session, so hold no long-lived reference to either: subscribe once through
|
||
<a class="xref" href="../api/Hi.MachiningProcs.LocalProjectService.html#Hi_MachiningProcs_LocalProjectService_OnShellMessageAdded">OnShellMessageAdded</a> /
|
||
<a class="xref" href="../api/Hi.MachiningProcs.LocalProjectService.html#Hi_MachiningProcs_LocalProjectService_OnShellMessageCleared">OnShellMessageCleared</a>, or buffer one call's messages
|
||
with <a class="xref" href="../api/Hi.Common.Messages.MessageCollector.html">MessageCollector</a>.</p>
|
||
<p><a class="xref" href="../api/Hi.MachiningProcs.MachiningSession.html">MachiningSession</a> takes an injected <a class="xref" href="../api/Hi.MachiningSteps.IMachiningService.html">IMachiningService</a>
|
||
host in its constructor, and <code>IMachiningService</code> replaces <code>PlayerCancellationToken</code> / <code>PausePlayer</code>
|
||
with a single <a class="xref" href="../api/Hi.Common.PacePlayer.html">PacePlayer</a> property.</p>
|
||
<h3 id="4-the-play-verbs">4. The play verbs</h3>
|
||
<p><code>Nc</code> becomes the umbrella term for any playable control program, and <code>BrandNc</code> names the
|
||
famous-brand controller-code group as a sibling of <code>Cl</code> and <code>Csv</code>.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Was</th>
|
||
<th>Is now</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>PlayNcFile(file)</code> — brand G-code only</td>
|
||
<td><a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_PlayNcFile_">PlayNcFile</a><code>(file, NcKind kind = NcKind.Auto)</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>RunNcFile(file)</code></td>
|
||
<td><a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_RunNcFile_">RunNcFile</a><code>(file, NcKind kind = NcKind.Auto)</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>the narrow brand-only file verbs</td>
|
||
<td><a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_PlayBrandNcFile_">PlayBrandNcFile</a> / <a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_RunBrandNcFile_">RunBrandNcFile</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>IControlRunner</code></td>
|
||
<td><code>Hi.Numerical.INcRunner</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>RunControlLines</code></td>
|
||
<td><a class="xref" href="../api/Hi.MachiningProcs.MachiningSession.html#Hi_MachiningProcs_MachiningSession_RunNcLines_">RunNcLines</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ControlKind</code></td>
|
||
<td><a class="xref" href="../api/Hi.MachiningProcs.NcKind.html">NcKind</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>IsRunningControlLines</code> / <code>BeginControlRunner</code></td>
|
||
<td><code>IsRunningNcLines</code> / <code>BeginNcRunner</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>the interim <code>PlayControlFile</code> / <code>RunControlFile</code> mirrors</td>
|
||
<td>removed</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>The same rename applies on <code>LocalProjectService</code>, <code>SessionShellController</code> and <code>MachiningSession</code>.
|
||
Only <code>.cl</code> / <code>.cls</code> / <code>.clsf</code> / <code>.csv</code> arguments change meaning —
|
||
<a class="xref" href="../api/Hi.MachiningProcs.NcKindUtil.html#Hi_MachiningProcs_NcKindUtil_DetectByPath_">DetectByPath</a> treats those as closed extension sets and
|
||
everything else falls back to brand G-code, so an exotic brand extension can never be misrouted.</p>
|
||
<h3 id="5-renames-with-no-shim">5. Renames with no shim</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Was</th>
|
||
<th>Is now</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>WorkpieceService.GetRuntimeGeom</code> / <code>ReadRuntimeGeom</code> / <code>WriteRuntimeGeom</code> / <code>SetRuntimeGeom</code> / <code>ResetRuntimeGeom</code> / <code>IsRuntimeGeomInit</code> / <code>ScanRuntimeGeomInfDefect</code></td>
|
||
<td><a class="xref" href="../api/Hi.NcMech.Workpieces.WorkpieceService.html#Hi_NcMech_Workpieces_WorkpieceService_GetOrBuildMeshedGeom_">GetOrBuildMeshedGeom</a> / <a class="xref" href="../api/Hi.NcMech.Workpieces.WorkpieceService.html#Hi_NcMech_Workpieces_WorkpieceService_ReadMeshedGeom_">ReadMeshedGeom</a> / <a class="xref" href="../api/Hi.NcMech.Workpieces.WorkpieceService.html#Hi_NcMech_Workpieces_WorkpieceService_WriteMeshedGeom_">WriteMeshedGeom</a> / <a class="xref" href="../api/Hi.NcMech.Workpieces.WorkpieceService.html#Hi_NcMech_Workpieces_WorkpieceService_SetMeshedGeom_">SetMeshedGeom</a> / <a class="xref" href="../api/Hi.NcMech.Workpieces.WorkpieceService.html#Hi_NcMech_Workpieces_WorkpieceService_ResetMeshedGeom_">ResetMeshedGeom</a> / <a class="xref" href="../api/Hi.NcMech.Workpieces.WorkpieceService.html#Hi_NcMech_Workpieces_WorkpieceService_IsMeshedGeomInit">IsMeshedGeomInit</a> / <a class="xref" href="../api/Hi.NcMech.Workpieces.WorkpieceService.html#Hi_NcMech_Workpieces_WorkpieceService_ScanMeshedGeomInfDefect_">ScanMeshedGeomInfDefect</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>MachiningEquipmentCollisionIndex.WorkpieceRuntimeGeomGetter</code></td>
|
||
<td><a class="xref" href="../api/Hi.Machining.MachiningEquipmentUtils.MachiningEquipmentCollisionIndex.html#Hi_Machining_MachiningEquipmentUtils_MachiningEquipmentCollisionIndex_WorkpieceMeshedGeomGetter">WorkpieceMeshedGeomGetter</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>IContourTray</code> / <code>UniformContourTray</code> / <code>FreeContourTray</code></td>
|
||
<td><a class="xref" href="../api/Hi.Milling.FluteContours.IFluting.html">IFluting</a> / <a class="xref" href="../api/Hi.Milling.FluteContours.UniformFluting.html">UniformFluting</a> / <a class="xref" href="../api/Hi.Milling.FluteContours.FreeFluting.html">FreeFluting</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>MillingCutter.FluteContourTray</code></td>
|
||
<td><a class="xref" href="../api/Hi.Milling.Cutters.MillingCutter.html#Hi_Milling_Cutters_MillingCutter_Fluting">Fluting</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Hi.Common.ResourceUtil</code> (the HiNc one)</td>
|
||
<td><a class="xref" href="../api/Hi.Common.ResourceLayout.html">ResourceLayout</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>NativeTopoStld</code> / <code>NativeTopoStlfr</code> / <code>NativeCarveTopoStl3wfr</code></td>
|
||
<td><a class="xref" href="../api/Hi.Geom.Topo.NativeTopoStl3d.html">NativeTopoStl3d</a> / <a class="xref" href="../api/Hi.Geom.Topo.NativeTopoStl3wfr.html">NativeTopoStl3wfr</a> / <a class="xref" href="../api/Hi.Geom.Topo.CarveStl.html">CarveStl</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Solid.NativeSmoothTopoStl</code> / <code>Sweptable.NativeTopoStl</code></td>
|
||
<td><a class="xref" href="../api/Hi.NcMech.Solids.Solid.html#Hi_NcMech_Solids_Solid_SmoothTopoStl3d">SmoothTopoStl3d</a> / <a class="xref" href="../api/Hi.Machining.Sweptable.html#Hi_Machining_Sweptable_NativeTopoStl3d">NativeTopoStl3d</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ITimeGetter</code> and its <code>Time</code> member</td>
|
||
<td><code>Hi.Physics.ITimecoded</code> and <code>Timecode</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ClStrip.DrawingRefreshing</code></td>
|
||
<td><code>ClStrip.DrawingRefreshed</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>CbtrPickable.CleanLinked*</code></td>
|
||
<td><code>CbtrPickable.CleanAttached*</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SoftNcRunner.NcDependencyList</code></td>
|
||
<td><a class="xref" href="../api/Hi.NcParsers.SoftNcRunner.html#Hi_NcParsers_SoftNcRunner_PipelineNcDependencyList">PipelineNcDependencyList</a></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Four notes on that table.</p>
|
||
<p>The <code>SessionShell</code> <strong>script</strong> names for meshed geometry keep hidden <code>[Obsolete]</code> aliases so existing
|
||
player scripts still run; the service-level members do not. <code>WorkpieceService.ResetRuntimeGeom</code> also
|
||
drops its <code>ClStrip</code> parameter.</p>
|
||
<p><code>ClStrip.DrawingRefreshed</code> was renamed because both invocations always fired <em>after</em> the work — the
|
||
<code>-ing</code> name told subscribers the opposite of when they are called. A subscriber that misses the
|
||
rename silently detaches.</p>
|
||
<p>Project and cutter files written before the fluting rename keep loading: each <code>Reg()</code> registers the
|
||
<code>ContourTray</code>-era XName beside the older aliases, and the cutter element reader tries <code>Fluting</code>, then
|
||
<code>FluteContourTray</code>, then <code>FluteContourTrackTray</code>. A cutter that nevertheless fails to resolve its
|
||
fluting machines as a plain bounding shape rather than failing loudly, so verify the load rather than
|
||
assuming it.</p>
|
||
<p><code>SoftNcRunner.PipelineNcDependencyList</code> is the raw list; machine-config consumers read the resolved
|
||
view through <a class="xref" href="../api/Hi.NcParsers.SoftNcRunner.html#Hi_NcParsers_SoftNcRunner_GetEffectiveNcDependencyList_">GetEffectiveNcDependencyList</a>. Legacy
|
||
<code><NcDependencyList></code> XML still loads and migrates.</p>
|
||
<h3 id="6-removals">6. Removals</h3>
|
||
<ul>
|
||
<li><strong>CSV</strong> — <code>CsvRunner0</code>, <code>LocalProjectService.EnableSoftCsvRunner</code>, and the earlier <code>RawCsvRunner</code>
|
||
and <code>CsvRowSemantic</code>. CSV playback has one path, <a class="xref" href="../api/Hi.Numerical.CsvParsers.GeneralCsvRunner.html">GeneralCsvRunner</a>,
|
||
and <a class="xref" href="../api/Hi.MachiningProcs.LocalProjectService.html#Hi_MachiningProcs_LocalProjectService_CsvRunner">CsvRunner</a> returns the CSV suit's
|
||
<a class="xref" href="../api/Hi.NcParsers.SoftNcRunner.html">SoftNcRunner</a> directly.</li>
|
||
<li><strong>Carriers</strong> — <code>IndexedSentence</code> (wrap a bare <code>Sentence</code> in your own
|
||
<a class="xref" href="../api/Hi.NcParsers.ISentenceCarrier.html">ISentenceCarrier</a> if you passed one as a <code>sourceCommand</code>),
|
||
<code>SimpleSessionCommand</code>, HiCbtr's <code>[Obsolete] LsStl</code>. The packed <code>MixedIndex</code> file-line key is
|
||
replaced by typed <a class="xref" href="../api/Hi.Common.FileLines.FileLineIndex.html">FileLineIndex</a> comparison, so file and line positions
|
||
compare by type rather than through a packed integer.</li>
|
||
<li><strong>GUI-layer composition</strong> — <code>MachiningProjectDisplayee</code>, <code>IsoCoordinateEntryDisplayee</code>,
|
||
<code>HeidenhainCoordinateEntryDisplayee</code>, <code>UserConfig</code>, <code>UserService</code>, <code>PlayerDivConfig</code>. Construct
|
||
<a class="xref" href="../api/Hi.MachiningProcs.LocalProjectService.html">LocalProjectService</a> with the <code>ILogger</code>-only constructor and copy the
|
||
displayees from any app project — <code>Hi.Sample.Wpf/Disp/</code> ships them. They compose only public API
|
||
(<a class="xref" href="../api/Hi.Disp.IDisplayee.html">IDisplayee</a> over <code>LocalProjectService</code>), so tailoring them is the point.</li>
|
||
<li><strong>Managed physics kernel types</strong> — the class <code>FluteZData</code>, <code>MillingForceUtil.RuntimePack</code> /
|
||
<code>LayerPack</code> / <code>AnglePack</code>, the <code>LayerMillingEngagement</code> constructor that built an engagement from a
|
||
z-to-dz list (the default and <code>BinaryReader</code> constructors stay), and
|
||
<code>MillingPhysicsBrief.YieldStressMinHeight_mm</code>.</li>
|
||
<li><strong>Culture declaration</strong> — <code>CultureUtil.SupportedCultureNames</code> and
|
||
<code>CultureUtil.SetCurrentCulture(string)</code>, deleted outright with no <code>[Obsolete]</code> shim. What remains is
|
||
<a class="xref" href="../api/Hi.Common.CultureUtil.html#Hi_Common_CultureUtil_English">English</a> and <a class="xref" href="../api/Hi.Common.CultureUtil.html#Hi_Common_CultureUtil_SetCurrentCultureEn_">SetCurrentCultureEn</a>. A host
|
||
that enumerated supported cultures must enumerate its own manual or resource folders instead.</li>
|
||
<li><strong>Dead P/Invoke declarations</strong> — eight <code>gl*</code> methods on HiDisp's public <code>GL</code> class (<code>glFenceSync</code>,
|
||
<code>glGetDoublev</code>, <code>glGetDoublei_v</code>, <code>glGetDoubleIndexedvEXT</code>, <code>glIglooInterfaceSGIX</code>,
|
||
<code>glPNTrianglesfATI</code>, <code>glPNTrianglesiATI</code>, and the already-commented <code>glDebugMessageCallbackAMD</code>).
|
||
They had no backing export and threw <code>EntryPointNotFoundException</code> when called.</li>
|
||
<li><strong><code>NcFileListCommand</code></strong> — a list of NC files is just a List of Program File commands, so
|
||
the dedicated type is gone. Loading a project that contains one converts it in place: each <code><File></code>
|
||
entry becomes a single-file <a class="xref" href="../api/Hi.SessionCommands.NcFileCommand.html">NcFileCommand</a> (kind <code>Auto</code>, the same
|
||
per-file extension dispatch) inside a <a class="xref" href="../api/Hi.SessionCommands.ListCommand.html">ListCommand</a>, and re-saving
|
||
persists the converted form.</li>
|
||
<li><strong>Post-Execution meshed-geometry output</strong> — <code>PostExecutionCommand</code> loses <code>EnableWriteMeshedGeom</code>
|
||
and <code>MeshedGeomFileTemplate</code> (and their pre-rename <code>…RuntimeGeom…</code> spellings) together with the
|
||
<code>enable-write-meshed-geom</code> and <code>meshed-geom-file-path</code> routes. A geometry snapshot can be taken at
|
||
any time-spot, unlike the run-derived outputs that command manages, so the carriers are now the
|
||
placeable <a class="xref" href="../api/Hi.SessionCommands.RecordMeshedGeomCommand.html">RecordMeshedGeomCommand</a> and
|
||
<a class="xref" href="../api/Hi.SessionCommands.ExportMeshedGeomToStlCommand.html">ExportMeshedGeomToStlCommand</a>. Loading an old project with the pair
|
||
enabled emits <code>PostExecution--MeshedGeomOutputRetired</code>, and re-saving drops the elements.</li>
|
||
</ul>
|
||
<h3 id="7-signature-and-shape-changes">7. Signature and shape changes</h3>
|
||
<ul>
|
||
<li><a class="xref" href="../api/Hi.Machining.MachiningToolHouse.html">MachiningToolHouse</a> derives from <code>Dictionary<int, IMachiningTool></code>:
|
||
<a class="xref" href="../api/Hi.Machining.MachiningToolHouse.html#Hi_Machining_MachiningToolHouse_SetToolId_">SetToolId</a> takes an <code>int</code> and
|
||
<a class="xref" href="../api/Hi.Machining.MachiningToolHouse.html#Hi_Machining_MachiningToolHouse_CreateStickMillingTool_">CreateStickMillingTool</a> returns
|
||
<code>KeyValuePair<int, MillingTool></code>. Any <code>(int)entry.Key</code> cast stops compiling. Siemens <code>T="name"</code>
|
||
string tool calls are unaffected — they still resolve to an <code>int</code> at the semantic layer.</li>
|
||
<li><a class="xref" href="../api/Hi.MachiningSteps.MachiningStep.html#Hi_MachiningSteps_MachiningStep_ActualTimecode">ActualTimecode</a> and
|
||
<a class="xref" href="../api/Hi.MachiningSteps.MachiningStep.html#Hi_MachiningSteps_MachiningStep_ActualDateTime">ActualDateTime</a> become get-only views onto the new optional
|
||
<a class="xref" href="../api/Hi.MachiningSteps.MachiningStep.html#Hi_MachiningSteps_MachiningStep_ActualTime">ActualTime</a> (<a class="xref" href="../api/Hi.MachiningSteps.StepActualTime.html">StepActualTime</a>) — their
|
||
setters are gone. <code>AccumulatedTime</code> is superseded by
|
||
<a class="xref" href="../api/Hi.MachiningSteps.MachiningStep.html#Hi_MachiningSteps_MachiningStep_EndTimecode">EndTimecode</a>, kept as an <code>[Obsolete]</code> alias; step CSVs write
|
||
the new header and still read the old.</li>
|
||
<li><a class="xref" href="../api/Hi.SessionCommands.PreSettingCommand.html">PreSettingCommand</a> becomes a legacy bundle. A saved bundle expands on load
|
||
into <a class="xref" href="../api/Hi.SessionCommands.MachiningResolutionCommand.html">MachiningResolutionCommand</a>,
|
||
<a class="xref" href="../api/Hi.SessionCommands.MachiningMotionResolutionCommand.html">MachiningMotionResolutionCommand</a>,
|
||
<a class="xref" href="../api/Hi.SessionCommands.CollisionDetectionCommand.html">CollisionDetectionCommand</a>,
|
||
<a class="xref" href="../api/Hi.SessionCommands.PauseOnFailureCommand.html">PauseOnFailureCommand</a> and <a class="xref" href="../api/Hi.SessionCommands.PhysicsCommand.html">PhysicsCommand</a> (plus a
|
||
Read-mode <code>RecordMeshedGeomCommand</code>), and is never written back. Anything that located the bundle
|
||
element in a saved <code>.hincproj</code> must look for the split commands.</li>
|
||
<li><code>ToPresentDto</code> wire keys change with the obfuscation fix: geometry DTOs use <code>Type</code> / <code>Min</code> / <code>Max</code> /
|
||
<code>PairZrs</code> / <code>Z</code> / <code>R</code> / <code>SourceFile</code> / <code>FileIndex</code> / <code>LineIndex</code> (<code>Vec3d</code> keeps lowercase <code>x</code> / <code>y</code> /
|
||
<code>z</code>), transformer DTOs use <code>Trans</code>, <code>Angle_deg</code>, <code>CosTheta</code> / <code>SinTheta</code>, <code>Axis</code>, <code>Pivot</code>, <code>Scale</code>,
|
||
<code>Rotation</code>, <code>Translation</code>, <code>Step</code>, <code>Stack</code>, <code>Matrix</code>. A front-end reading those payloads must be
|
||
updated in lockstep.</li>
|
||
<li><a class="xref" href="../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_defaultFontFile">defaultFontFile</a> changes value from <code>"Font/WCL06.ttf"</code> to <code>"(embedded)"</code>.
|
||
It is a public <code>const</code>, so an assembly compiled against 3.1.175 already carries the old literal and
|
||
keeps passing it — <code>Init</code> still accepts it — but a rebuild changes what it passes, and no font file
|
||
is extracted to the working directory any more.</li>
|
||
</ul>
|
||
<h3 id="8-defaults-and-gates-that-changed">8. Defaults and gates that changed</h3>
|
||
<ul>
|
||
<li><a class="xref" href="../api/Hi.MachiningProcs.LocalProjectService.html#Hi_MachiningProcs_LocalProjectService_EnableSoftNcRunner">EnableSoftNcRunner</a> defaults to <code>true</code>. The SoftNc
|
||
pipeline is the NC engine; <a class="xref" href="../api/Hi.Numerical.FilePlayers.HardNcRunner.html">HardNcRunner</a> is the opt-out fallback for
|
||
the shrinking set of features still bound to it.</li>
|
||
<li><a class="xref" href="../api/Hi.MillingForces.MillingForceUtil.html#Hi_MillingForces_MillingForceUtil_EnableNativeMillingPhysics">EnableNativeMillingPhysics</a> defaults to <code>true</code>, and in a
|
||
<strong>shipping build</strong> setting it to <code>false</code> throws <code>InvalidOperationException</code> at the setter — the
|
||
managed reference implementation lives only in a non-shipping assembly. Code that flipped it off for
|
||
an A/B comparison now fails at configuration time.</li>
|
||
<li><a class="xref" href="../api/Hi.MillingForces.MillingPhysicsBrief.html#Hi_MillingForces_MillingPhysicsBrief_YieldingStressRatio">YieldingStressRatio</a> and
|
||
<a class="xref" href="../api/Hi.MachiningSteps.MachiningStep.html#Hi_MachiningSteps_MachiningStep_YieldingStressRatio">YieldingStressRatio</a> report <strong><code>NaN</code></strong> instead of <code>0</code> when no
|
||
beam section qualifies. A caller treating <code>0</code> as “no yielding constraint” — as both feed solvers did
|
||
— must add a <code>NaN</code> branch or it will pass <code>NaN</code> into downstream queries.</li>
|
||
<li><strong>New licence feature <code>NcComposition</code> (id 22).</strong> Registering any non-built-in processing unit into a
|
||
<a class="xref" href="../api/Hi.NcParsers.SoftNcRunner.html">SoftNcRunner</a> pipeline, or executing an NC-embedded C# script, requires it.
|
||
Degradation is silent and functional: external units are skipped for the session with one
|
||
<code>Composition--NotLicensed</code> naming them, an external segmenter falls back to <code>SingleLineSegmenter</code>,
|
||
and scripts are skipped with <code>Script--NotLicensed</code>. An unlicensed installation therefore produces a
|
||
<em>different simulation</em>, not an error. Calling the public API from your own application or session
|
||
script needs no extra licence; composing the interpretation pipeline does. See
|
||
<a href="../fundamentals/nc-parsing/index.html">NC Parsing Engine</a>.</li>
|
||
<li>The four <code>SnapshotSyntax</code> entries in the Fanuc preset default to <code>IsEnabled = false</code>, so projects
|
||
stop serializing enabled debug snapshots. A project saved by an earlier build keeps what it
|
||
serialized until its pipeline list is refreshed from the current preset.</li>
|
||
<li><strong>Server side</strong>: HiNcServer pins request localization to <a class="xref" href="../api/Hi.Common.CultureUtil.html#Hi_Common_CultureUtil_English">English</a>, so an
|
||
<code>Accept-Language: zh-Hant</code> request falls back to <code>en</code>. HiNcRcl removes the
|
||
<code>HiNC:DisplayEngine:FontFile</code> configuration key, which never had any effect — delete it from
|
||
<code>appsettings</code>. <a class="xref" href="../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_FontFile">FontFile</a> remains for a custom font.</li>
|
||
<li><strong>Localization</strong>: HiMech's <code>MachiningStep.zh-Hant</code> / <code>.zh-Hans</code> resx are deleted. Step presentation
|
||
strings now come from the HiNc-Resource present catalog (<code>catalog.en.json</code>, <code>catalog.zh-Hant.json</code>,
|
||
<code>catalog.zh-Hans.json</code>) that a host overlays; a host that ships neither loses the localized step
|
||
labels it used to get for free.</li>
|
||
<li><strong>Packaging is x64-only</strong>: HiDisp drops the <code>win-x86</code> runtime identifier and its Sentinel payload,
|
||
HiNc-Resource drops the x86 platform.</li>
|
||
<li><strong>The shipped machine-tool packages are renamed.</strong> They now carry the <code>.default</code> marker and neutral
|
||
names: <code>MachineTool/Table-B1.default</code> and <code>MachineTool/CT-350.default</code>. The table-type package was
|
||
renamed outright — its <code>.mt</code>, its <code>.general-mech</code> and its STL headers travel with it — and the
|
||
duplicated nested STL set inside the CT-350 package is deleted. A project, script or <code>.mt</code> that
|
||
refers to a shipped machine-tool package by its earlier path must be repointed at the name above.</li>
|
||
</ul>
|
||
<h2 id="results-that-change-on-upgrade">Results that change on upgrade</h2>
|
||
<p>None of the following breaks a build. All of them change what a simulation produces, so a
|
||
byte-for-byte comparison against 3.1.175 output will differ — usually because 3.1.175 was wrong.</p>
|
||
<p><strong>Silent wrong geometry, now fixed.</strong> Each of these produced a plausible-looking simulation of the
|
||
wrong thing.</p>
|
||
<ul>
|
||
<li><strong>The kinematic pivot anchor.</strong> The pivot-transform chain entry was built as <code>K(0)·K(abc)⁻¹</code>,
|
||
folding the whole machine-zero forward kinematic — its linear part included — into the pre-pivot
|
||
anchor. That linear part encodes each axis' motion sense and tool/workpiece-side ownership, so it
|
||
mirrored the program components of every workpiece-side linear axis before the IK ran. On a
|
||
table-side chain whose machine-zero linear part is <code>diag(1,1,-1)</code>, every program Z was mirrored and
|
||
a near-180° swing amplified it into metres of machine-Z error, floating the toolpath above the
|
||
workpiece. The anchor is now the translation alone, matching what HardNc has always kept. Machines
|
||
whose linear axes all ride the tool side are unaffected.</li>
|
||
<li><strong>G68 2D coordinate rotation was a silent no-op.</strong> <a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.TiltTransformUtil.html">TiltTransformUtil</a>
|
||
judged the active mode from the current block but always took the matrix from the previous one, so
|
||
every G68 activation past the first block had its freshly authored rotation overwritten with an
|
||
identity that then propagated. G68 rotation did nothing at all while the block's term still read
|
||
<code>G68</code>, and the simulation machined the unrotated pattern. Re-running an existing G68 program now
|
||
gives different — correct — geometry.</li>
|
||
<li><strong>A blank line reset G90/G91.</strong> A piece with no parsing section — a blank line, a comment-only line,
|
||
<code>%</code>, an O-number — left the next block's single-step lookback empty, and it fell back to the G90
|
||
default. A program that was incremental throughout silently flipped to absolute mid-file. Such
|
||
pieces now carry the positioning section forward like every other modal syntax.</li>
|
||
<li><strong>A Siemens D offset with no <code>$TC_DP</code> row resolved to zero length, in silence.</strong> A whole TRAORI
|
||
program machined one tool length low. The read point now falls back to the generic tool-number-keyed
|
||
height and emits <code>SiemensToolOffset--TcdpRowMissing</code>.</li>
|
||
<li><strong>G43.4 with an unresolvable H word activated RTCP with a zero-length tool.</strong> It now reports
|
||
<code>Comp-ToolHeight--001</code> as a warning and keeps processing the block. An absent H stays silent —
|
||
re-activating G43.4 on the modal offset id is legitimate input.</li>
|
||
<li><strong>Heidenhain DIN/ISO arc centres.</strong> <code>I</code> / <code>J</code> / <code>K</code> are <strong>absolute</strong> circle centres on Heidenhain —
|
||
the ISO face of the klartext <code>CC</code> pole — not start-to-centre offsets. Reading them incrementally
|
||
turned arcs into near-full phantom circles. Fixed in all three engines: the HardNc reader
|
||
(<a class="xref" href="../api/Hi.Numerical.NcArgs.ArcNcArg.html#Hi_Numerical_NcArgs_ArcNcArg_IsIjkAbsolute">IsIjkAbsolute</a>), the SoftNc reader
|
||
(<a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.CircularMotionSyntax.html#Hi_NcParsers_LogicSyntaxs_CircularMotionSyntax_IsIjkAbsolute">IsIjkAbsolute</a>) and the optimizer's write-back.
|
||
Also delivered on the 3.1.175.x service line.</li>
|
||
<li><strong>A <code>K0</code> word on a HardNc G02/G03 saturated the turn count.</strong> Under the default G17 plane a
|
||
written-but-zero plane-normal word divided the axial travel by zero, the additional-turn count
|
||
saturated to <code>int.MaxValue</code>, and one arc block became a spiral act of roughly 302 simulated years —
|
||
the play appeared to hang on a single NC line. The reading now falls back to the closed-circle rule
|
||
for a zero pace, matching the guard the SoftNc side already had.</li>
|
||
<li><strong>Indexed-rotary programs folded the pivot into plain moves.</strong> A block with no active G68.2 or
|
||
G43.4 no longer folds the kinematic pivot transform into a plain XYZ move, which is what a real
|
||
controller does with a table-side rotary program.</li>
|
||
<li><strong>The radius-compensation arc transient cache landed on the wrong block.</strong> Any non-motion line
|
||
between the corner and the arc orphaned the cache, so the arc lost its leading linear bridge and
|
||
began at the corner intersection instead of on the offset arc.</li>
|
||
<li><strong>The G68.2 tool-axis IK fallback probed the mirrored tool axis.</strong> Both normal-only fallbacks in
|
||
<a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.IsoG68p2TiltSyntax.html">IsoG68p2TiltSyntax</a> read the transposed third column instead of the
|
||
third row. On the no-hint path this only skewed a warning gate, but the explicit A/B/C path seeds
|
||
its hint blend from that solve, so a machine with fewer than three rotary axes composed a mirrored
|
||
tilted plane.</li>
|
||
<li><strong>A Fanuc <code>WHILE</code> forward jump bound to the wrong <code>END</code>.</strong> Sequential loops idiomatically reuse
|
||
<code>DO 1</code>, so a second <code>WHILE</code>'s falsy-condition exit bound to the <em>first</em> loop's <code>END 1</code> and
|
||
redirected execution to a point before the second <code>WHILE</code> — an unbounded loop the iteration
|
||
watchdog cannot see, because it only ticks on <code>END</code> reverse jumps. The jump now uses the anchored
|
||
label scan the Siemens loop family already used.</li>
|
||
<li><strong>Heidenhain G28 is MIRROR IMAGE, not a reference-point return.</strong> On the Heidenhain preset the
|
||
shared pipeline had been reading it as the Fanuc reference return, so a <code>G28 X</code> block minted a
|
||
phantom rapid to home while the mirror silently vanished. It is now simulated as a program-to-MC
|
||
transform, <code>ReferenceReturnSyntax</code> leaves the Heidenhain logic list, and klartext <code>CYCL DEF 8</code>
|
||
records the same mirror statement so one program mirrors identically in either dialect. <strong>HardNc
|
||
keeps the Fanuc reading</strong>, so the two engines are deliberately divergent on Heidenhain G28 files and
|
||
any parity comparison must account for it.</li>
|
||
<li><strong><code>MathUtil.Convert_inchdmin_To_mmds</code> returned mm/min, not mm/s.</strong> The body multiplied by 25.4 and
|
||
never divided by 60, so a caller trusting the name got a 60× feedrate; the sibling
|
||
<code>Convert_mmdmin_To_mmds</code> divides as its name demands. No shipped path called it — the CL/APT
|
||
feedrate route converts inches-per-minute to mm/min itself — so this changes nothing inside the
|
||
product, but a caller who had compensated for the old behaviour must remove that compensation.</li>
|
||
<li><strong><code>GetRByZ(List<PairZr>)</code> never interpolated.</strong> The list overload looked up its ceiling node with
|
||
the floor lookup, so floor equalled ceiling and the method degenerated into a step function. For a
|
||
sharp cone whose inner-beam Z–R list has no node between apex and rim, that pinned the inner radius
|
||
to 0 across the whole cone face and produced NaN flute vertices — the root cause of the transparent
|
||
cone-tip flute that 3.1.180 addressed at the display layer. It affects every consumer of
|
||
radius-by-Z interpolation, force geometry included.</li>
|
||
</ul>
|
||
<p><strong>Numerical results move even where nothing was renamed.</strong></p>
|
||
<ul>
|
||
<li>Five-axis IK is roughly <strong>1000× tighter</strong>. The rotary solver behind
|
||
<a class="xref" href="../api/Hi.Numerical.Xyzabc.XyzabcSolver.html">XyzabcSolver</a> now runs coarse→polish: the coarse stage keeps the
|
||
original dot residual so solve success and failure
|
||
semantics are unchanged, then a <code>[dot, cross, rr-per-axis]</code> system polishes. The dot criterion is
|
||
quadratically blind to angle error — an envelope of about 1.4e-3 rad, and the resulting tip error is
|
||
that envelope times the tool length — so adding the cross term restores quadratic convergence and
|
||
drops the envelope to about 1e-6 rad. Failed solves no longer pollute the implicit seed, and the
|
||
measure-zero perfect-saddle case is escaped by a deterministic retry offset instead of by leftover
|
||
seed pollution.</li>
|
||
<li><a class="xref" href="../api/Hi.Numerical.Acts.ActMcXyzLinearContour.html">ActMcXyzLinearContour</a> steps by <strong>euclidean</strong> tip travel instead of the
|
||
largest per-axis component, so <code>LinearResolution_mm</code> now caps actual tool-tip travel per step and a
|
||
diagonal move produces up to √3× more steps at the same setting.</li>
|
||
<li>The SoftNc pipeline is the default engine.</li>
|
||
<li>Executed <code>SyntaxPiece</code>s freeze to UTF-8 (below), so their <code>JsonObject</code> is a fresh read-only snapshot
|
||
per call rather than a retained live graph.</li>
|
||
<li><code>SyntaxPiece.SentenceIndex</code> becomes a session-global execution-order counter and is no longer
|
||
contiguous per file.</li>
|
||
<li>Repeated NC diagnostics fold into per-run summaries at the run boundaries.</li>
|
||
<li><strong>HardNc tool changes</strong> fire on M06 / Heidenhain <code>TOOL CALL</code> rather than on a changed <code>T</code> word — a
|
||
bare <code>T</code> is magazine pre-selection, and a same-tool M06 still runs the changer cycle — and unset
|
||
<code>HardNcEnv</code> tooling defaults become the three-axis shape (XYZ = NaN, NaN, 0; ABC all NaN). The old
|
||
defaults swung all three rotary axes home on every M06, which no post expects.</li>
|
||
</ul>
|
||
<h2 id="brand-nc-language-coverage">Brand NC language coverage</h2>
|
||
<p>The SoftNc pipeline is the default NC engine, and this is where most of the release went.</p>
|
||
<h3 id="siemens-sinumerik">Siemens SINUMERIK</h3>
|
||
<p>Real <code>.mpf</code> / <code>.spf</code> programs replay end to end, not an ISO subset. At 3.1.175 a program that declared
|
||
its tool as <code>T="NAME"</code>, shifted with <code>SUPA</code>, computed with R-parameters, called L-subprograms or
|
||
looped with <code>WHILE</code> was not interpreted past that point.</p>
|
||
<ul>
|
||
<li><strong>Modal vocabulary</strong> — <code>SUPA</code> / <code>G153</code> suppress all frames for one block; <code>T="NAME"</code> string tool
|
||
calls with <code>D</code> cutting-edge offsets resolved through
|
||
<a class="xref" href="../api/Hi.NcParsers.Dependencys.Siemens.SiemensToolOffsetTable.html">SiemensToolOffsetTable</a> (<code>$TC_DP</code> lengths and radius plus
|
||
additive wear); <code>G70</code> / <code>G71</code> units; path smoothing (<code>G60x</code> / <code>G64x</code>, <code>FNORM</code> / <code>SOFT</code> / <code>FFWON</code> /
|
||
<code>COMP*</code> / <code>UPATH</code>, <code>CYCLE832</code>); <code>MSG()</code> and <code>STOPRE</code>; <code>CR=</code> and <code>TURN=</code> arcs. Tail comments became
|
||
quote-aware, so a <code>;</code> inside <code>MSG("A;B")</code> no longer truncates the block, and the preset stops
|
||
misreading <code>L</code> and <code>G74</code> as Fanuc-family codes.</li>
|
||
<li><strong>Evaluation</strong> — <a class="xref" href="../api/Hi.NcParsers.EvaluationSyntaxs.Siemens.SiemensExpressionParser.html">SiemensExpressionParser</a> feeds the
|
||
shared expression engine, so <code>Z=R63+150</code> and <code>X=SIN(R10)*20</code> drive motion.
|
||
<a class="xref" href="../api/Hi.NcParsers.Dependencys.Siemens.SiemensRParameterTable.html">SiemensRParameterTable</a> holds R0–R999 as per-case project
|
||
data, <code>DEF REAL/INT</code> declarations lower into assignments, and <code>$P_UIFR[n,axis,TR]</code> binds both ways
|
||
to <a class="xref" href="../api/Hi.NcParsers.Dependencys.Siemens.SiemensFrameTable.html">SiemensFrameTable</a>. Any other <code>$</code>-variable is recorded
|
||
with an unsupported note rather than dropped.</li>
|
||
<li><strong>Five axis</strong> — <a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.Siemens.SiemensProgrammableFrameSyntax.html">SiemensProgrammableFrameSyntax</a> simulates
|
||
<code>TRANS</code> / <code>ATRANS</code> / <code>ROT</code> / <code>AROT</code> (with <code>RPL=</code>) into the tilt-transform chain in Sinumerik RPY
|
||
order; <a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.Siemens.SiemensTraoriSyntax.html">SiemensTraoriSyntax</a> makes <code>TRAORI</code> a real RTCP mode,
|
||
the sibling of ISO G43.4, with <code>TRAFOOF</code> handing the offset back;
|
||
<a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.Siemens.SiemensCycle800TiltSyntax.html">SiemensCycle800TiltSyntax</a> decodes <code>CYCLE800</code>'s MODE bits for
|
||
all four swivel modes. <code>ROTS</code> / <code>SCALE</code> / <code>MIRROR</code> are recognized and reported, not simulated.</li>
|
||
<li><strong>Calls</strong> — L-prefixed and named subprogram calls resolve against
|
||
<a class="xref" href="../api/Hi.NcParsers.Dependencys.Generic.SubProgramFolderConfig.html">SubProgramFolderConfig</a> (<code>{name}.SPF</code>, then <code>.MPF</code>, then the
|
||
bare name) and inline with their <code>P</code> repetition count; <code>M17</code> / <code>RET</code> pop a frame; <code>REPEAT</code> re-runs a
|
||
labelled slice; <code>MCALL CYCLE81/82/83/85</code> maps onto the shared canned-cycle machinery; <code>PROC</code> headers
|
||
and labels are claimed whole.</li>
|
||
<li><strong>Control flow</strong> — <code>GOTOF</code> / <code>GOTOB</code>, <code>IF</code> / <code>ELSE</code> / <code>ENDIF</code>, and <code>WHILE</code> / <code>FOR</code> / <code>REPEAT-UNTIL</code> /
|
||
<code>LOOP</code>. Runaway programs are bounded rather than hanging the session:
|
||
<a class="xref" href="../api/Hi.NcParsers.Dependencys.Siemens.SiemensGotoIterationDependency.html">SiemensGotoIterationDependency</a> caps jumps per (file, label)
|
||
and <a class="xref" href="../api/Hi.NcParsers.Dependencys.Siemens.SiemensLoopIterationDependency.html">SiemensLoopIterationDependency</a> caps iterations per
|
||
(file, loop-entry line); over the cap the construct warns and falls through.</li>
|
||
<li><strong>Per-word coordinate functions</strong> — <code>AC()</code> / <code>IC()</code> / <code>DC()</code> / <code>ACP()</code> / <code>ACN()</code>, including on
|
||
<code>I</code> / <code>J</code> / <code>K</code> circle centres. <code>G90 C=IC(360/17)</code> is one incremental index inside an absolute
|
||
program. Direction resolution lives in <a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.McAbcCyclicPathSyntax.html">McAbcCyclicPathSyntax</a>:
|
||
<code>ACP()</code> takes the <code>[anchor, anchor+360)</code> window, <code>ACN()</code> the <code>(anchor-360, anchor]</code> window, <code>DC()</code>
|
||
the shortest swing, with the exact 180° tie going negative.</li>
|
||
<li><strong>Coded positions</strong> — <code>CAC</code> / <code>CIC</code> / <code>CDC</code> / <code>CACP</code> / <code>CACN</code> take a 1-based indexing position
|
||
number rather than a coordinate, resolved against <a class="xref" href="../api/Hi.NcParsers.Dependencys.IIndexingPositionConfig.html">IIndexingPositionConfig</a>,
|
||
implemented by <a class="xref" href="../api/Hi.NcParsers.Dependencys.Siemens.SiemensMachineDataTable.html">SiemensMachineDataTable</a> from the real machine
|
||
data (the MD30500 axis assignment, the MD10910 / MD10930 position tables, the equidistant
|
||
MD30501–30503 definition).</li>
|
||
<li><strong><code>G74</code> / <code>G75</code> fixed-point return</strong> is claimed as a whole block, so its dummy axis values no longer
|
||
mint a rapid to the coordinates written in the block and its <code>F</code> never reaches the modal feedrate.</li>
|
||
<li><strong>OEM auxiliary M-codes</strong> — the preset declares <code>M12</code> / <code>M13</code> / <code>M22</code> / <code>M23</code> and <code>M330</code> / <code>M331</code>
|
||
note-only, so each occurrence voices <code>DeclaredMCode--UnmodeledEffects</code> instead of an unknown-code
|
||
warning, without inventing simulated effects. A machine's own table overrides a declaration when the
|
||
real effects are known.</li>
|
||
</ul>
|
||
<h3 id="heidenhain">Heidenhain</h3>
|
||
<p>Both dialects play on one preset, <a class="xref" href="../api/Hi.NcParsers.SoftNcRunner.html#Hi_NcParsers_SoftNcRunner_HeidenhainNcRunner">HeidenhainNcRunner</a>.</p>
|
||
<ul>
|
||
<li><strong>Klartext motion and setup</strong> — the <code>L</code> statement and its axis words, <code>FMAX</code>, <code>M91</code> as a one-shot
|
||
machine-coordinate move, <code>TOOL CALL</code> wired to tool change and spindle speed with the table height
|
||
and <code>DL</code>. Datum handling follows TNC semantics: <code>CYCL DEF 247</code> sets the preset and <code>CYCL DEF 7</code> is an
|
||
<em>additive</em> shift on top of it, composing as separate transform-chain entries instead of replacing
|
||
each other, resolved against <a class="xref" href="../api/Hi.NcParsers.Dependencys.HeidenhainDatumTable.html">HeidenhainDatumTable</a>. Arcs (<code>CC</code> pole
|
||
plus <code>C</code> statement, <code>DR-</code> = CW, implicit centre, closed arc = full circle), <code>RL</code> / <code>RR</code> / <code>R0</code> radius
|
||
compensation, the <code>M126</code> / <code>M127</code> rotary-wrap state, <code>M140 MB</code> retract, and <code>CYCL DEF 32 TOLERANCE</code>.</li>
|
||
<li><strong>Q-parameters</strong> — <a class="xref" href="../api/Hi.NcParsers.EvaluationSyntaxs.Heidenhain.HeidenhainExpressionParser.html">HeidenhainExpressionParser</a> lexes
|
||
<code>Q</code> / <code>QR</code> / <code>QL</code> / <code>QS</code>, the <code>DIV</code> keyword of FN 4 and the prefix <code>SQRT</code> of FN 5, so <code>FQ1</code> reaches
|
||
the feedrate, <code>L X+Q2</code> reaches the program XYZ and <code>TOOL CALL SQ3</code> reaches the spindle speed.
|
||
<a class="xref" href="../api/Hi.NcParsers.Dependencys.Heidenhain.HeidenhainQParameterTable.html">HeidenhainQParameterTable</a> holds Q0–Q99 free and QR0–QR499
|
||
permanent parameters as per-case project data. Unimplemented opcodes (FN 14 / 16 / 18…) are claimed
|
||
and reported rather than half-read, so an <code>FN 18 SYSREAD</code> target stays vacant instead of taking a
|
||
fabricated value. <strong>FN 9–12 conditional jumps execute</strong>, with a (file, label)-keyed iteration cap.</li>
|
||
<li><strong>Tilt and RTCP</strong> — <code>PLANE</code> (SPATIAL fully composed with <code>SEQ</code> / <code>COORD ROT</code> / <code>TABLE ROT</code> and
|
||
<code>STAY</code> / <code>MOVE</code> / <code>TURN</code> positioning; VECTOR structurally captured; EULER / POINTS / RELATIV /
|
||
AXIAL / PROJECTED consumed and warned with the previous tilt retained, so a <code>PLANE AXIAL B+45</code> B
|
||
word can never be mistaken for a rotary axis command), <code>FUNCTION TCPM</code>, and real <code>M128</code> / <code>M129</code>
|
||
tool-centre-point control.</li>
|
||
<li><strong>Cycles and calls</strong> — <code>CYCL DEF 2xx</code> bodies with their Q parameters mirrored into the block
|
||
assignments, cycles 200 / 232 / 251 / 252 / 253 mapped onto the shared G81 / G82 / G83 slots,
|
||
<code>CYCL CALL</code> / <code>CYCL CALL POS</code> / <code>M99</code> / <code>M89</code> splitting call-once from modal firing, <code>CALL LBL</code>
|
||
inlining up to <code>LBL 0</code>, <code>CALL LBL n REP m</code> as a section repeat, and <code>CALL PGM</code> resolved by file
|
||
name. The multi-line tilde continuation form is joined at segmentation
|
||
(<a class="xref" href="../api/Hi.NcParsers.Segmenters.HeidenhainSegmenter.html#Hi_NcParsers_Segmenters_HeidenhainSegmenter_JoinTildeContinuations">JoinTildeContinuations</a>, on by default).</li>
|
||
<li><strong>Post-processed spellings</strong> — some post-processors write a whole klartext body with no separators
|
||
at all, which used to yield zero motion. Glued line shapes (<code>LX-26.3Y+43.1</code>, <code>FMAXM03M08</code>,
|
||
<code>…R0FMAX</code>) and the detached feed spelling (<code>F 20000</code>) now parse, with <code>M140</code>, <code>M128</code> and
|
||
<code>PLANE MOVE</code> widening their own <code>F</code> capture so a retract or feed-limit value cannot leak into the
|
||
modal feedrate. <code>BLK FORM</code> is recorded as a brand-neutral stock declaration without replacing the
|
||
project workpiece setup, and the klartext <code>STOP</code> word joins <code>M00</code> / <code>M01</code>.</li>
|
||
<li><strong>DIN/ISO dialect</strong> — <code>%</code> tape header, <code>N</code> block numbers, <code>T</code> + <code>M06</code>, absolute <code>I</code> / <code>J</code> / <code>K</code> arc
|
||
centres with the modal pole carried forward, the ISO label family (<code>G98 L<n></code> definitions and the
|
||
head-anchored <code>L<n>,<m></code> call mapping the comma count onto <code>REP</code>), <code>G247 Q339</code> stamping the same
|
||
datum preset as <code>CYCL DEF 247</code>, <code>G54</code> with axis words read as a datum-shift declaration, and
|
||
<code>G70</code> / <code>G71</code>.</li>
|
||
</ul>
|
||
<h3 id="fanuc-and-iso-common">Fanuc and ISO common</h3>
|
||
<ul>
|
||
<li><strong>Polar coordinate interpolation</strong> — <code>G12.1</code> / <code>G13.1</code> on the SoftNc pipeline. Before this a polar
|
||
section parsed silently wrong: the <code>X</code> word (a diameter) and the <code>C</code> word (a hypothetical Cartesian
|
||
axis in mm) were consumed as ordinary XYZ and rotary degrees.
|
||
<a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.ProgramRxczSyntax.html">ProgramRxczSyntax</a> halves <code>X</code> from diameter, resolves G90/G91, writes
|
||
the polar and derived Cartesian positions and the machine C angle, and classifies motion into polar
|
||
linear and polar arc — the latter emitting <a class="xref" href="../api/Hi.Numerical.Acts.ActMcPolarSpiralContour.html">ActMcPolarSpiralContour</a>, which
|
||
keeps spiral geometry in central polar coordinates and stays continuous across ±180°. <code>G41</code> / <code>G42</code>
|
||
compensation is resolved on the hypothetical plane, a C-axis speed clamp applies, and YA / ZB axis
|
||
pairs are supported. <a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.PolarGCodeCheckSyntax.html">PolarGCodeCheckSyntax</a> scans for incompatible G
|
||
codes before the mode syntaxes consume them.</li>
|
||
<li><strong>Custom Macro B</strong> — <code>#var</code> assignment with range-routed stores (<code>#1</code>–<code>#33</code> local per macro frame,
|
||
<code>#100</code>–<code>#499</code> volatile cleared on M02/M30, <code>#500</code>–<code>#999</code> retained and persisted in the project,
|
||
<code>#3000</code>–<code>#3999</code> system-control), boolean and logical operators, <code>IF[..]GOTO n</code>, <code>IF[..]THEN <stmt></code>,
|
||
<code>WHILE[..]DO m / END m</code> with a bounded-loop watchdog, and position and tool-offset system variables.
|
||
<code>M98 P_ L_</code>, <code>M198</code> external call, <code>M99</code> return and <code>M99 P{seq}</code> early return; <code>G65</code> one-shot macro
|
||
call with A–Z → <code>#1</code>–<code>#26</code> argument binding, and <code>G66</code> / <code>G67</code> modal macro.</li>
|
||
</ul>
|
||
<h3 id="cross-brand">Cross-brand</h3>
|
||
<ul>
|
||
<li><strong>A shared <code>DwellSyntax</code></strong> consumes <code>G4</code> and <code>G04</code> with the dialect held on the instance:
|
||
Fanuc-family <code>X</code> / <code>U</code> seconds, <code>P</code> milliseconds, <code>S</code> spindle revolutions; the Siemens instance reads
|
||
<code>F</code> seconds and <code>S</code> revolutions. Capturing the <code>G04</code> spelling fixes a real defect — the un-captured
|
||
spelling fell through to the flag and axis syntaxes, where a Fanuc <code>G04 X0.5</code> dwell time became a
|
||
ghost X motion word.</li>
|
||
<li><strong>Machine-declared M-codes</strong> — <a class="xref" href="../api/Hi.NcParsers.Dependencys.IMCodeDeclarationConfig.html">IMCodeDeclarationConfig</a> and
|
||
<a class="xref" href="../api/Hi.NcParsers.Dependencys.MCodeEffects.html">MCodeEffects</a> let a machine state what its own OEM codes do (composite
|
||
spindle+coolant codes, a tool-change trigger, turret <code>T</code>-word semantics), and
|
||
<a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.MCodeExpansionSyntax.html">MCodeExpansionSyntax</a> expands a declared code into the canonical ISO
|
||
flags the shared consumers already understand.</li>
|
||
<li><strong>Custom spindle M-codes</strong> drive the spindle direction through a machine-level
|
||
<a class="xref" href="../api/Hi.NcParsers.Dependencys.ISpindleControlConfig.html">ISpindleControlConfig</a>; ISO <code>M03</code> / <code>M04</code> / <code>M05</code> remain the built-in
|
||
fallback. An <code>S</code> greater than zero with no direction ever issued assumes clockwise and emits
|
||
<code>SpindleDirection--AssumedCw</code>, so the physics gate no longer silently produces zero mechanics for a
|
||
whole file.</li>
|
||
<li><strong>Tool changes synthesize their axis travel.</strong>
|
||
<a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.ToolChangeMotionSyntax.html">ToolChangeMotionSyntax</a> overlays the per-axis tooling position from
|
||
<a class="xref" href="../api/Hi.NcParsers.Dependencys.IToolingMcConfig.html">IToolingMcConfig</a> onto the current pose (a NaN or missing axis stays
|
||
put) and stamps a one-item rapid compound motion, and
|
||
<a class="xref" href="../api/Hi.NcParsers.Semantics.ToolChangeSemantic.html">ToolChangeSemantic</a> moves behind
|
||
<a class="xref" href="../api/Hi.NcParsers.Semantics.CompoundMotionSemantic.html">CompoundMotionSemantic</a> so the tooling step lands at the tooling point.
|
||
Programs that retract on their own overlay to a zero-length move and emit nothing extra.</li>
|
||
<li><strong>Per-brand pivot gates.</strong> <a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.PivotTransformationSyntax.html">PivotTransformationSyntax</a> reverts to the
|
||
ISO/Fanuc vocabulary (G43.4 plus the G68.x family),
|
||
<a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.Siemens.SiemensPivotTransformationSyntax.html">SiemensPivotTransformationSyntax</a> gates TRAORI / CYCLE800, and
|
||
<a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.Heidenhain.HeidenhainPivotTransformationSyntax.html">HeidenhainPivotTransformationSyntax</a> gates the M128 /
|
||
PLANE vocabulary. All three compose the identical entry through the shared
|
||
<a class="xref" href="../api/Hi.NcParsers.LogicSyntaxs.PivotTransformUtil.html">PivotTransformUtil</a>. <strong>Exactly one brand gate belongs in a pipeline
|
||
list — never register two.</strong></li>
|
||
<li><strong>Controller presets are writable and shipped.</strong> A controller resource file is one serialized
|
||
<a class="xref" href="../api/Hi.NcParsers.SoftNcRunner.html">SoftNcRunner</a> — the whole pipeline that decides how a brand's NC code is
|
||
interpreted. <a class="xref" href="../api/Hi.NcParsers.ControllerPresetWriter.html">ControllerPresetWriter</a> serializes the built-in brand presets
|
||
(<code>CreateBrandPreset</code>, <code>WriteBrandPresetFile</code>, <a class="xref" href="../api/Hi.NcParsers.ControllerPresetWriter.html#Hi_NcParsers_ControllerPresetWriter_WriteAllBrandPresetFiles_">WriteAllBrandPresetFiles</a>)
|
||
under <code>Resource/Controller/</code> with the <code>.Controller</code> extension, and HiNc-Resource ships all five so the
|
||
load browser starts populated. The static brand properties remain the source of truth; the files are
|
||
regenerable snapshots. Writing needs no <code>XFactory</code> registration — reading one back does, because the
|
||
loader drops unregistered pipeline entries silently rather than failing the load.</li>
|
||
<li><strong>Saved pipelines back-fill their system-wired dependencies on load.</strong> A project saved before a
|
||
system-wired dependency existed never self-healed by round-tripping, because re-saving stamped a
|
||
fresh API version on the same incomplete list. The <a class="xref" href="../api/Hi.NcParsers.SoftNcRunner.html">SoftNcRunner</a> XML constructor
|
||
now appends the missing ones after the legacy version patches. A runner rehydrated from an older
|
||
file still keeps the <em>syntax</em> list it was saved with, though — take the regenerated preset, or a
|
||
fresh <a class="xref" href="../api/Hi.NcParsers.NcRunnerSuit.html">NcRunnerSuit</a> built from it, rather than expecting an old file to grow new
|
||
syntaxes.</li>
|
||
<li><strong>Machine-coordinate and tilted-plane failures report.</strong> G53 and G53.1 record their source G-code
|
||
on the parsed block and emit <code>Coord-MachCoord--005</code> / <code>--006</code> / <code>--007</code> on paths that used to fail
|
||
silently. A G68.2 tilted plane the machine cannot reach emits <code>Coord-Tilt--001</code> / <code>--002</code>, with a
|
||
tool-axis-only IK retry that avoids a spurious warning on a machine with fewer than three rotary
|
||
axes.</li>
|
||
<li><strong>Session-global sentence indexing.</strong> <code>SyntaxPiece.SentenceIndex</code> used to be assigned by two
|
||
independent sequences, so indices collided as soon as a call was inlined mid-stream. The new
|
||
<a class="xref" href="../api/Hi.NcParsers.Dependencys.SystemWired.SentenceIndexCounterDependency.html">SentenceIndexCounterDependency</a> supplies every index at
|
||
one chokepoint, so values are session-globally unique and strictly increasing in execution order,
|
||
including nested and repeated calls.</li>
|
||
<li><strong>Inline plays can loop and jump, and playing a file no longer holds it open.</strong> Inline NC-code plays
|
||
stamp their pieces with the command title as a pseudo-path, and every control-flow re-segmentation
|
||
re-read the host file by that path — the existence check always failed, so loops fell through
|
||
without looping. <code>RunNc</code> now registers the raw lines on
|
||
<a class="xref" href="../api/Hi.NcParsers.Dependencys.SystemWired.NcLineSourceDependency.html">NcLineSourceDependency</a> and
|
||
<a class="xref" href="../api/Hi.NcParsers.EvaluationSyntaxs.LabelScanUtil.html">LabelScanUtil</a> reads memory first, disk second.</li>
|
||
</ul>
|
||
<h2 id="nc-optimization-and-writeback">NC optimization and writeback</h2>
|
||
<div class="IMPORTANT">
|
||
<h5>Important</h5>
|
||
<p><strong>NC optimization is not finished on the 3.2 line.</strong> What follows describes the leg as it stands,
|
||
and it is published for review, not for production. Work that depends on optimized output should
|
||
stay on the 3.1 line, serviced as <code>3.1.175.<patch></code>.</p>
|
||
</div>
|
||
<ul>
|
||
<li><strong>The optimizer runs on the SoftNc pipeline by default.</strong>
|
||
<a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_OptimizeToFiles_">OptimizeToFiles</a> keeps its signature, its script snippet and
|
||
its HTTP route, but when <a class="xref" href="../api/Hi.MachiningProcs.LocalProjectService.html#Hi_MachiningProcs_LocalProjectService_EnableSoftNcRunner">EnableSoftNcRunner</a> is on and
|
||
the session holds played <a class="xref" href="../api/Hi.MachiningProcs.NcRunnerSessionState.html#Hi_MachiningProcs_NcRunnerSessionState_SyntaxPieceLayers">SyntaxPieceLayers</a>, it
|
||
delegates to the new <a class="xref" href="../api/Hi.MachiningProcs.MachiningSession.html#Hi_MachiningProcs_MachiningSession_OptimizeNcFiles_">OptimizeNcFiles</a>; otherwise the frozen
|
||
HardNc path runs unchanged. The new leg classifies the final
|
||
<a class="xref" href="../api/Hi.NcParsers.Syntaxs.SyntaxPiece.html">SyntaxPiece</a> layer, solves the per-step feed adjustments from milling
|
||
physics, and regenerates text as anchored token edits over the verbatim source block — <strong>lines the
|
||
optimizer does not touch round-trip byte-identically</strong> instead of being re-synthesized. Per-file
|
||
results are retained in <a class="xref" href="../api/Hi.MachiningProcs.MachiningSession.html#Hi_MachiningProcs_MachiningSession_NcOptimizations">NcOptimizations</a>.
|
||
<a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_EnableIndividualStepAdjustmentLog">EnableIndividualStepAdjustmentLog</a> drives both legs.</li>
|
||
<li><strong>Depth splition re-interpolates through a planned fragment path</strong>, with separate modal chains for
|
||
the pre-build feed and the emission endpoint, per-step machine-to-program-frame inversion, and arc
|
||
IJK recomputation including R-to-IJK conversion. Two cases where the frozen HardNc optimizer is
|
||
silently wrong are downgraded to a non-split rewrite rather than reproduced: a <code>G91</code> incremental
|
||
block (the old fragment rewrite always emitted absolute coordinates), and a Heidenhain klartext block
|
||
(the rewrite would splice ISO-shaped I/J/K words into a block whose arc centre comes from a preceding
|
||
modal block).</li>
|
||
<li><strong>The compensation stage is no longer dead on the SoftNc leg.</strong> The HardNc baseline wrote the
|
||
compensation into the step contexts while its output read the piece packs, so it never emitted a
|
||
compensated coordinate at all. Each fragment endpoint is now offset — XYZ only, rotary words
|
||
untouched — by the tool-tip deflection rotated into the leaf program frame the endpoint lives in, so
|
||
a G68.2 tilted setup is compensated in the right direction. It is consumed on re-interpolated
|
||
splition fragments only, and <a class="xref" href="../api/Hi.NcOpt.NcOptOption.html#Hi_NcOpt_NcOptOption_CompensationMask">CompensationMask</a> defaults to 0, so with no
|
||
mask set the stage is a strict no-op.</li>
|
||
<li><strong>Output follows the source's decimal digits.</strong> Both legs used to write coordinates through a fixed
|
||
<code>F4</code> and every F word through <code>F2</code>, so a program stated to three decimals could come back with a
|
||
fourth — an alarm on controllers strict about their least input increment. Digit counts are now
|
||
scanned per word family over the played source texts with comment spans masked, floored at 3/3/0 and
|
||
capped at 9, and threaded through the whole write path. The word-suppression tolerances and the F
|
||
comparison grid derive from the resolved digits instead of the old fixed literals.</li>
|
||
<li><strong>Optimized NC is written back in the source file's encoding.</strong> NC play reads and optimized writes go
|
||
through <a class="xref" href="../api/Hi.Common.FileLines.FileUtil.html#Hi_Common_FileLines_FileUtil_DetectRoundTripEncoding_">DetectRoundTripEncoding</a> — BOM, then strict UTF-8, then
|
||
Latin-1 — so an ANSI-family file (GBK, Big5, Shift-JIS) re-encodes to its original bytes instead of
|
||
having every undecodable byte replaced. Comments in those encodings survive the round trip.</li>
|
||
<li><strong>A feed change no longer mints a one-step carrier fragment.</strong> Under an arc split that fragment is a
|
||
degenerate arc whose start and end nearly coincide, which an incremental-IJK reader — or a control
|
||
that treats begin == end as a full turn — expands into a full circle. An <code>F</code> re-statement is now
|
||
handed to the feed run's next emitted fragment, the one that actually runs at that feed.</li>
|
||
<li><strong>A splition fragment at the head of the stream writes only the axis words the source stated</strong>, so it
|
||
can no longer invent a <code>Z0.</code> whose value under the source's silence is just the home-fallback modal.</li>
|
||
<li><strong>Unparsable NC lines survive.</strong> A line the parser could not read used to be dropped from the runner's
|
||
line list, so the optimized file silently lost it. <code>HardNcRunner</code> now rebuilds a parse-failed line as
|
||
an opaque no-op — the empty-text parse inherits modal state like a blank line, and the raw text is
|
||
restored for writers — and the optimizer mirrors the fallback, so <code>IF</code> blocks, <code>#</code>-variable macros,
|
||
<code>G68 R#</code> and <code>GOTO</code> come through verbatim. A <code>BuildNcLines--ParseFailed</code> diagnostic still reports the
|
||
line, and the line stays un-simulated. The output writer is also closed in a <code>finally</code>, so an
|
||
exception can no longer leave a half-written file locked. First delivered on the 3.1.175.x service
|
||
line.</li>
|
||
<li><strong>A Siemens <code>CYCLE800</code> swivel counts as a macro line</strong> in the piece classifier, so it is preserved
|
||
rather than treated as an optimizable motion block.</li>
|
||
<li><strong>The host key <code>HiNC:OptCoreNum</code> governs both legs again.</strong> It used to set only the legacy
|
||
<code>NcOptProc.CoreNum</code>; once the SoftNc optimizer became the default path the key silently stopped
|
||
governing anything. It now assigns both (0 = derive from the processor count).</li>
|
||
<li><strong>NC text writeback</strong> regenerates NC from a program that has already been played, in two stages over
|
||
the session's finished syntax pieces: a converter turns the source piece stream into a destination
|
||
stream plus a bidirectional source↔destination map keyed by sentence index, and a reverse segmenter
|
||
serializes that stream back to lines. The data→text seam is a brand-agnostic sentence composer, first
|
||
implemented for Fanuc. A patch-mode writer performs positional token edits — <code>NaN</code> deletes a word
|
||
absorbing one separator space, insertion follows conventional order, trailing zeros trim keeping the
|
||
dot — and refuses to rewrite variable, bracket and keyword values rather than corrupting them,
|
||
reporting <code>Writeback-Patch--VariableValue</code>, <code>--KeywordValue</code>, <code>--CommentOnlyText</code> and
|
||
<code>--EditUnmatched</code>.</li>
|
||
<li><strong>A second diagnostic home.</strong> <a class="xref" href="../api/Hi.MachiningSteps.IMachiningService.html#Hi_MachiningSteps_IMachiningService_NcManipulationDiagnosticProgress">NcManipulationDiagnosticProgress</a>
|
||
is a sibling of the play-time <code>NcDiagnosticProgress</code>, dedicated to NC-rework operations — writeback
|
||
conversion and optimization — so a play reset never discards manipulation results and vice versa.</li>
|
||
</ul>
|
||
<h2 id="milling-physics-training-and-measured-data">Milling physics, training and measured data</h2>
|
||
<ul>
|
||
<li><strong>Physics runs in the native kernel.</strong> The per-step milling physics migrated into <code>core.dll</code> in
|
||
stages: the engagement is scan-converted natively at the substraction completion point, the force
|
||
kernel is reached through the same handle with no managed marshal, and the sequential
|
||
cutting-temperature and wear chain runs from a native thermal session held per (tool, cutting
|
||
parameter) pack. The switch is
|
||
<a class="xref" href="../api/Hi.MillingForces.MillingForceUtil.html#Hi_MillingForces_MillingForceUtil_EnableNativeMillingPhysics">EnableNativeMillingPhysics</a>, surfaced runtime-only (not
|
||
persisted to project XML) as <a class="xref" href="../api/Hi.MachiningProcs.MachiningActRunnerConfig.html#Hi_MachiningProcs_MachiningActRunnerConfig_EnableNativeMillingPhysics">EnableNativeMillingPhysics</a>
|
||
and <a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_EnableNativeMillingPhysics">EnableNativeMillingPhysics</a>, and it now defaults to <code>true</code>.
|
||
Public entry points that used to reach the managed kernel still work: without a session pack they
|
||
build an ad-hoc physics pack per live (cutting parameter, tool) pair and run natively.</li>
|
||
<li><strong><a class="xref" href="../api/Hi.Milling.MillingTools.MillingToolPhysicsPack.html">MillingToolPhysicsPack</a></strong> is an immutable record holding one tool's
|
||
scalar derivations for one cutting-parameter set — spindle-buckle-to-tip length, observation height,
|
||
effective cutting diameter, the bending/Z-deflection pair, the simplified rake angle, the minimum
|
||
uncut chip thickness. <a class="xref" href="../api/Hi.MachiningProcs.MachiningSession.html">MachiningSession</a> owns the packs keyed by tool id
|
||
(<a class="xref" href="../api/Hi.MachiningProcs.MachiningSession.html#Hi_MachiningProcs_MachiningSession_GetToolPhysicsPack_">GetToolPhysicsPack</a>) and invalidation is <strong>explicit</strong> at
|
||
the points that know the state changed: every run-op start and the tool-change act, plus
|
||
<a class="xref" href="../api/Hi.MachiningProcs.MachiningSession.html#Hi_MachiningProcs_MachiningSession_InvalidateToolPhysicsPacks_">InvalidateToolPhysicsPacks</a>. The corresponding
|
||
<code>MillingTool</code> / <code>MillingCutter</code> members are now deliberately uncached pure computations.</li>
|
||
<li><strong>Milling-force waveforms are reproducible again.</strong> The parallel per-step force build read lazily
|
||
built scalar caches on the shared tool objects; a thread could pass a cache guard and then read a
|
||
value a concurrent writer had stored in between, so two plays of the same NC exported different
|
||
forces in the thin-chip window of each tooth pass. The caches were first republished as single
|
||
immutable references and then removed in favour of the frozen session pack.</li>
|
||
<li><strong>Thermal gating and seeding.</strong> The sequential cutting-temperature and wear build now checks
|
||
<a class="xref" href="../api/Hi.MachiningProcs.MachiningActRunnerConfig.html#Hi_MachiningProcs_MachiningActRunnerConfig_EnablePhysics">EnablePhysics</a> (spindle temperature deliberately
|
||
keeps running), and the tool-change thermal seeding re-arms whenever the incoming chain state has no
|
||
flute temperature list — which covers fault and cancel re-seeds, stop-then-replay residue, and
|
||
<code>EnablePhysics</code> being switched on mid-session. The shank temperature list is seeded to the exact node
|
||
count the thermal FEM builds, so trailing shank nodes no longer sit at 0 K after a tool change.</li>
|
||
<li><strong>Cutter geometry is validated up front.</strong>
|
||
<a class="xref" href="../api/Hi.Milling.Cutters.MillingCutter.html#Hi_Milling_Cutters_MillingCutter_GetUpperBeamGeometryIssues_">GetUpperBeamGeometryIssues</a> collects upper-beam and shank
|
||
configuration problems as keyed messages — for example an extended-cylinder beam whose full length
|
||
sits below the flute height (<code>Cutter-UpperBeam--BelowFluteHeight</code>), which inverts the shank solid and
|
||
makes the shank thermal model unbuildable. They are reported once per tool at <code>BeginSession</code> and at
|
||
each tool change, instead of surfacing later as a null-reference cascade inside the thermal physics
|
||
with nothing naming the beam.</li>
|
||
<li><strong><code>RakeFaceCuttingPara3d</code> no longer throws on a six-field parameter string</strong> (the guard read the
|
||
seventh element behind a <code>>= 6</code> check), and the published coefficient index mappings are corrected:
|
||
the <code>LocalProfileMillingPara(Vec3d, Vec3d)</code> constructor maps (x,y,z) to (Ksr, Kst, Ksa) /
|
||
(Kpr, Kpt, Kpa), and the 2d element index range is 0–3 with 0=Ksc, 1=Ksn, 2=Kpc, 3=Kpn.</li>
|
||
<li><strong>Training diagnostics name their cause.</strong> The per-step warnings split into
|
||
<code>Train-StepLuggage--Unreadable</code> (the step luggage row could not be read back) and
|
||
<code>Train-StepEngagement--Missing</code> (the row is present but the engagement was never built because
|
||
physics was inactive at simulation time). The gather pass counts both against the eligible steps:
|
||
silent at zero, one summary warning at or below
|
||
<a class="xref" href="../api/Hi.MillingForces.Training.MillingTraining.html#Hi_MillingForces_Training_MillingTraining_MissingEngagementAbortRatio">MissingEngagementAbortRatio</a> (default 0.25), and a
|
||
configuration error above it. A gather pass that produces no samples at all now reports immediately
|
||
rather than throwing inside the SVD solve, separating “not one step touched the workpiece” from
|
||
“touched steps whose mapped force data yielded no usable shots”.</li>
|
||
<li><strong>New training knobs.</strong> <a class="xref" href="../api/Hi.MillingForces.Training.MillingTraining.html#Hi_MillingForces_Training_MillingTraining_EnableDesignMatrixSolver">EnableDesignMatrixSolver</a>
|
||
(default false) solves the least squares on a thin QR of the design matrix instead of forming the
|
||
normal equations, which square the condition number;
|
||
<a class="xref" href="../api/Hi.MillingForces.Training.MillingTraining.html#Hi_MillingForces_Training_MillingTraining_DesignMatrixSvdRelativeTol">DesignMatrixSvdRelativeTol</a> is its truncation cutoff.
|
||
<a class="xref" href="../api/Hi.MillingForces.Training.MillingTraining.html#Hi_MillingForces_Training_MillingTraining_EnableCwePhasePairing">EnableCwePhasePairing</a> (default false) determines each
|
||
step's rotation phase with a cutter-workpiece-engagement block-pairing detector instead of the
|
||
self-bootstrapped lead parameter, for one-flute and symmetric two-flute cutters in light radial side
|
||
cuts. <a class="xref" href="../api/Hi.MillingForces.Training.MillingTraining.html#Hi_MillingForces_Training_MillingTraining_ReTrainAnchorOutputScale">ReTrainAnchorOutputScale</a> exposes the virtual
|
||
anchor weight.
|
||
<a class="xref" href="../api/Hi.MachiningProcs.LocalProjectService.html#Hi_MachiningProcs_LocalProjectService_LastMillingParaTrainResult">LastMillingParaTrainResult</a> captures the outcome — kind,
|
||
sample flags, outlier ratio, success, output file, parameter name and note, correlation R, filtered
|
||
sample count, parameter XML, timestamp — so a caller reads it without re-opening the <code>.mp</code> file.</li>
|
||
<li><strong>Time mapping is reworked around absolute wall-clock time.</strong>
|
||
<a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_AddTimeDataByFile_">AddTimeDataByFile</a> accepts <code>DateTime</code> windows, stored as
|
||
<a class="xref" href="../api/Hi.Mappings.IFileTimeSection.html">IFileTimeSection</a> forms, and the project-scoped
|
||
<a class="xref" href="../api/Hi.Mapping.TimeMapping.html#Hi_Mapping_TimeMapping_MappingAnchorDateTime">MappingAnchorDateTime</a> — seeded set-once from the date of the first
|
||
controller instant seen — converts controller timestamps onto one run-relative axis.
|
||
<a class="xref" href="../api/Hi.MachiningSteps.MachiningStep.html#Hi_MachiningSteps_MachiningStep_EndTimecode">EndTimecode</a> replaces <code>AccumulatedTime</code> as the canonical
|
||
end-of-step time.</li>
|
||
<li><strong>CSV timing survives midnight.</strong> Step durations derive from full date-bearing instants, so a
|
||
multi-day recording no longer produces negative durations and a negative chart time axis, and a
|
||
non-physical duration from a spliced recording is clamped with a validation warning instead of
|
||
stalling physics evaluation.</li>
|
||
<li><strong>Wall-clock time is dense.</strong> The trio moved into one optional sub-object,
|
||
<a class="xref" href="../api/Hi.MachiningSteps.StepActualTime.html">StepActualTime</a> (<code>Timecode</code> / <code>Instant</code> / <code>IsInterpolated</code>), reached through
|
||
<a class="xref" href="../api/Hi.MachiningSteps.MachiningStep.html#Hi_MachiningSteps_MachiningStep_ActualTime">ActualTime</a>. On CSV plays every built step is stamped: steps
|
||
built from a controller row re-anchor, and the steps between extrapolate along the machine timeline
|
||
and are marked interpolated, which makes the actual-time mapper window per-step exact instead of
|
||
sparse-anchor scaled. Pure NC plays keep null stamps.</li>
|
||
<li><strong>An empty step-shot pairing window is a data gap, not something to interpolate across.</strong> The window
|
||
builder used to expand outward to the rows bracketing the gap, silently pairing such steps with force
|
||
values that were never measured — a training run over a file whose transients had been carved out
|
||
produced a plausible correlation and a full set of coefficients derived entirely from fabricated
|
||
rows. Such a window now skips its step and one <code>Map-ShotGap--StepsSkipped</code> warning per mapping call
|
||
carries the count; a window-edge row is interpolated only when its bracketing rows span at most two
|
||
spindle revolutions.</li>
|
||
<li><strong>“No cut / No data for step” on freshly-simulated steps is fixed.</strong> The bulk step-data readers
|
||
cached the <em>absence</em> of rows the writer had not committed yet, so a step that had just been
|
||
simulated could report no data until the program was re-run. A covered-but-missing index now drops
|
||
the stale segment and re-reads.</li>
|
||
<li><strong>New end-of-play warnings</strong>, each once per session: <code>Play-Touch--None</code> (the play finished without any
|
||
step touching the workpiece), <code>Tool-FluteCount--Zero</code> (physics is on and a milling cutter resolves to
|
||
zero flutes, so feed per tooth is undefined), and <code>Play-Physics--None</code> (physics is on and at least one
|
||
step touched the workpiece but no touched step carries a physics brief — naming the three things that
|
||
gate it: a tool bound to the spindle, the spindle actually rotating, and the workpiece cutting
|
||
parameter). That last state previously surfaced one process later, as a training run gathering zero
|
||
samples.</li>
|
||
<li><strong>Performance</strong> is collected in its own section below.</li>
|
||
</ul>
|
||
<h2 id="cutter-location-cl-playback-and-cl-to-nc">Cutter-location (CL) playback and CL-to-NC</h2>
|
||
<ul>
|
||
<li><strong>Replay an NX CLSF / APT-source toolpath directly.</strong>
|
||
<a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_PlayClFile_">PlayClFile</a> reads <code>MSYS</code> / <code>FROM</code> / <code>GOTO</code> / <code>CIRCLE</code> /
|
||
<code>RAPID</code> / <code>FEDRAT</code> / <code>SPINDL</code> / <code>COOLNT</code> / <code>TLDATA</code> / <code>LOAD</code>. The parser is the
|
||
<a class="xref" href="../api/Hi.Numerical.ClsfParsers.NxClRunner.html">NxClRunner</a> preset — a <a class="xref" href="../api/Hi.NcParsers.SoftNcRunner.html">SoftNcRunner</a> composition —
|
||
and the project holds a third runner suit <a class="xref" href="../api/Hi.MachiningProcs.MachiningProject.html#Hi_MachiningProcs_MachiningProject_ClsfRunnerSuit">ClsfRunnerSuit</a>
|
||
beside the NC and CSV suits. A <code>TLDATA</code> record creates the tool geometry when the tool house has no
|
||
matching id. Run-ops are first class: <a class="xref" href="../api/Hi.MachiningSteps.IMachiningService.html#Hi_MachiningSteps_IMachiningService_ClRunner">ClRunner</a>,
|
||
<code>MachiningSession.PlayClFile</code> / <code>RunClFile</code>. See
|
||
<a href="../manual/runtime/cutter-location-playback.html">Cutter-Location (CL) Playback</a>.</li>
|
||
<li><strong>A CL file can now drive a machine-tool chain</strong>, not only a
|
||
<a class="xref" href="../api/HiMachining.Milling.ClMillingDevice.html">ClMillingDevice</a>. When the pipeline's kinematics dependency resolves to a
|
||
live solver, <a class="xref" href="../api/Hi.Numerical.ClsfParsers.ClToMcTransformSyntax.html">ClToMcTransformSyntax</a> inverse-solves every CLSF motion
|
||
endpoint at parse time and expresses the result in the same <code>ProgramToMcTransform</code> vocabulary the NC
|
||
pipeline uses — a tool-height entry from the active tool, a pivot entry anchored to the workpiece
|
||
frame, and the solved rotary axes in raw degrees for the cyclic wrap tail-pass — so <code>McLinear</code> and
|
||
the wrap are reused unchanged. Played onto a <code>ClMillingDevice</code> the same file is still pure
|
||
cutter-location motion, which is what you want for verifying a CAM toolpath before any post-processor
|
||
is involved.</li>
|
||
<li><strong>CL moves resample along the true path.</strong> <a class="xref" href="../api/Hi.Numerical.Acts.ActUtil.html#Hi_Numerical_Acts_ActUtil_GetClSteps_">GetClSteps</a> walks
|
||
<code>IClPath.At</code> for each intermediate step rather than linearly interpolating between the path's begin
|
||
and end, so a CL arc actually curves and the tool axis rotates <em>along</em> the path instead of through
|
||
it. <a class="xref" href="../api/Hi.CutterLocations.ClPath.ClLinear.html">ClLinear</a> gained two guards on the same path: the near-parallel
|
||
begin/end normal case short-circuits instead of falling into a degenerate cross product that yielded
|
||
a NaN rotation axis, and the interpolation reads its rotation delta through the lazily-built property
|
||
rather than a still-null backing field.</li>
|
||
<li><strong>CL tool changes teleport instead of stepping.</strong> A stepping change stamps collision detection and
|
||
volume removal at the chain's current pose, and at CL session start that pose is identity — the tool
|
||
sitting at program zero inside the workpiece. The CSV pipeline's teleporting semantic is promoted to
|
||
the shared <a class="xref" href="../api/Hi.NcParsers.Semantics.ToolingTeleportSemantic.html">ToolingTeleportSemantic</a> (the old <code>CsvToolingTeleportSemantic</code>
|
||
element name is kept as a load-only alias), and the first <code>GOTO</code> after a <code>LOAD</code> / <code>TOOL</code> is forced
|
||
into a reposition so a new tool never sweeps a cut from the previous operation's endpoint.</li>
|
||
<li><strong>Convert a played CL program into Fanuc NC files.</strong>
|
||
<a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_ConvertClToNcFiles_">ConvertClToNcFiles</a>, its HTTP action, and the
|
||
<code>LocalProjectService</code> / <code>MachiningSession</code> entry points walk the session's final syntax-piece layer,
|
||
group pieces per source file and write one NC file per source, template-substituting <code>[NcName]</code>
|
||
(default <code>Output/[NcName].nc</code>). It requires a prior play on a machine chain — a pure-CL device leaves
|
||
no machine-solved sections to serialize — and reports <code>ConvertClToNc--NoPlay</code> otherwise. Stage-one
|
||
results are retained in <a class="xref" href="../api/Hi.MachiningProcs.MachiningSession.html#Hi_MachiningProcs_MachiningSession_NcConversions">NcConversions</a> as the hook for
|
||
source↔output cross-navigation. A mission can declare the writeback through
|
||
<a class="xref" href="../api/Hi.SessionCommands.PostExecutionCommand.html#Hi_SessionCommands_PostExecutionCommand_EnableConvertClToNcFiles">EnableConvertClToNcFiles</a> and
|
||
<a class="xref" href="../api/Hi.SessionCommands.PostExecutionCommand.html#Hi_SessionCommands_PostExecutionCommand_ClToNcFileTemplate">ClToNcFileTemplate</a>.</li>
|
||
<li><strong>CL→MC hardening.</strong> Tool-offset resolution walked back to the distant <code>LOAD</code> block for every motion
|
||
(O(N²) on production-scale files) and is now O(1) through a modal active-tool section; the
|
||
documentary program-to-Pn stamp is stamped once per run rather than walked per motion; the
|
||
program-zero query no longer deep-clones the whole equipment assembly per motion block; the
|
||
warned-tool-id set is run-scoped, so the <code>ClToMc--NoToolOffset</code> warning is no longer suppressed on
|
||
every run after the first; and <a class="xref" href="../api/Hi.NcParsers.Dependencys.Generic.MachineAxisConfig.html">MachineAxisConfig</a> gains a
|
||
public <code>Clear()</code> so a machine switch rebuilds the axis table instead of accumulating stale rotary
|
||
axes.</li>
|
||
</ul>
|
||
<h2 id="session-project-and-command-model">Session, project and command model</h2>
|
||
<ul>
|
||
<li><strong>A parser and its per-case data travel as one file.</strong> <a class="xref" href="../api/Hi.NcParsers.NcRunnerSuit.html">NcRunnerSuit</a> bundles a
|
||
runner with the dependency data a particular job needs, as a single file-loadable unit. The project
|
||
holds three suits — <a class="xref" href="../api/Hi.MachiningProcs.MachiningProject.html#Hi_MachiningProcs_MachiningProject_NcRunnerSuit">NcRunnerSuit</a>,
|
||
<a class="xref" href="../api/Hi.MachiningProcs.MachiningProject.html#Hi_MachiningProcs_MachiningProject_CsvRunnerSuit">CsvRunnerSuit</a> and
|
||
<a class="xref" href="../api/Hi.MachiningProcs.MachiningProject.html#Hi_MachiningProcs_MachiningProject_ClsfRunnerSuit">ClsfRunnerSuit</a> — and
|
||
<a class="xref" href="../api/Hi.MachiningProcs.LocalProjectService.html#Hi_MachiningProcs_LocalProjectService_ReadNcRunnerSuit_">ReadNcRunnerSuit</a> /
|
||
<a class="xref" href="../api/Hi.MachiningProcs.LocalProjectService.html#Hi_MachiningProcs_LocalProjectService_WriteNcRunnerSuit_">WriteNcRunnerSuit</a> switch the active parser mid-project
|
||
from a suit file. A switch attempted while a program is playing is refused with
|
||
<code>ReadNcRunnerSuit--Refused</code>.</li>
|
||
<li><strong>One NC runner configuration is shareable across projects.</strong> Per-case data — tool offsets,
|
||
work-coordinate offsets, Siemens frames, Heidenhain datums, retained macro variables, seeded brand
|
||
parameter tables — travels as proxy placeholders inside <a class="xref" href="../api/Hi.NcParsers.SoftNcRunner.html">SoftNcRunner</a> and
|
||
resolves against the owning project's per-case list, so a controller configuration is no longer
|
||
welded to the job it was first built for. Machine-config consumers read the resolved view through
|
||
<a class="xref" href="../api/Hi.NcParsers.SoftNcRunner.html#Hi_NcParsers_SoftNcRunner_GetEffectiveNcDependencyList_">GetEffectiveNcDependencyList</a>; legacy <code><NcDependencyList></code> XML and
|
||
<code>NcEnv</code>-based projects still load and migrate automatically.</li>
|
||
<li><strong>HTTP guards and one envelope.</strong> <a class="xref" href="../api/Hi.MachiningProcs.RequireActiveSessionAttribute.html">RequireActiveSessionAttribute</a> answers a
|
||
session-scoped action with HTTP 409 and an <code>ApiActionResult.NoActiveSession()</code> body when no session is
|
||
active, instead of the previous null-reference 500;
|
||
<a class="xref" href="../api/Hi.MachiningProcs.RequireLoadedProjectAttribute.html">RequireLoadedProjectAttribute</a> does the same for the project-level controller.
|
||
Both are applied at the controller level and honour opt-out markers
|
||
(<a class="xref" href="../api/Hi.MachiningProcs.AllowNoActiveSessionAttribute.html">AllowNoActiveSessionAttribute</a>,
|
||
<a class="xref" href="../api/Hi.MachiningProcs.AllowNoLoadedProjectAttribute.html">AllowNoLoadedProjectAttribute</a>). Mutating actions inject a fresh
|
||
<a class="xref" href="../api/Hi.Common.Messages.MessageCollector.html">MessageCollector</a> and return the collected notifications inline in the
|
||
shared <a class="xref" href="../api/Hi.MachiningProcs.ApiActionResult.html">ApiActionResult</a> envelope, so a REST or AI caller sees progress,
|
||
success and error messages in the response instead of only out of band.
|
||
<a class="xref" href="../api/Hi.MachiningProcs.LocalProjectServiceController.html">LocalProjectServiceController</a> exposes the project-level (session-independent)
|
||
surface parallel to <a class="xref" href="../api/Hi.MachiningProcs.SessionShellController.html">SessionShellController</a>.</li>
|
||
<li><strong>Session commands declare themselves.</strong> <a class="xref" href="../api/Hi.SessionCommands.CommandCatalogAttribute.html">CommandCatalogAttribute</a> marks an
|
||
<a class="xref" href="../api/Hi.SessionCommands.ISessionCommand.html">ISessionCommand</a> as user-addable and places it in a
|
||
<a class="xref" href="../api/Hi.SessionCommands.CommandCategory.html">CommandCategory</a> (Setup / Program / Optimization / Output / Flow, declaration
|
||
order = display order) with an <code>Order</code> sort key and an optional wire kind (default: the class name
|
||
minus the <code>Command</code> suffix, lower-cased). <a class="xref" href="../api/Hi.SessionCommands.CommandFieldAttribute.html">CommandFieldAttribute</a> marks a
|
||
bool / int / double / string property as a directly editable scalar with an optional label, unit and
|
||
physics-licence flag, so a generic editor renders and updates it without a hand-written form. A
|
||
command without the catalog attribute stays loadable from project files but is not offered for
|
||
creation.</li>
|
||
<li><strong>Program File dispatches by kind.</strong> <a class="xref" href="../api/Hi.SessionCommands.NcFileCommand.html">NcFileCommand</a> gains an <code>NcKind</code>
|
||
property (XML element <code>NcKind</code>, absent = <code>Auto</code> for legacy projects) and its mission label becomes
|
||
“Program File”; each command resolves its own file, so a List of Program Files can mix
|
||
brand NC, CL and CSV.</li>
|
||
<li><strong>Two session commands saved but could never be read back.</strong> <code>ListCommand.Reg</code> chained every type
|
||
except <a class="xref" href="../api/Hi.SessionCommands.NcOptOptionCommand.html">NcOptOptionCommand</a> and
|
||
<a class="xref" href="../api/Hi.SessionCommands.RecordMeshedGeomCommand.html">RecordMeshedGeomCommand</a>, so any XML round-trip of an entry holding one threw
|
||
<code>KeyNotFoundException</code> out of the <a class="xref" href="../api/Hi.Common.XmlUtils.XFactory.html">XFactory</a> generator lookup — reloading a
|
||
saved project containing an NC Optimization Config command failed. Both are now chained.</li>
|
||
<li><strong>Naming.</strong> <a class="xref" href="../api/Hi.SessionCommands.ListCommand.html#Hi_SessionCommands_ListCommand_Title">Title</a> is an optional name shown in place of the type
|
||
name, so nested command lists can be named in the mission tree. <code>PreSettingCommand</code> displays as
|
||
“General Config” and <code>NcOptOptionCommand</code> as “NC Optimization Config” — display strings only, so
|
||
serialization and endpoints are untouched. A bare non-list <code>PlayerCommand</code> root is normalized on read
|
||
into a single enabled entry of the default <code>ListCommand</code>. Command titles, catalog categories and field
|
||
labels are now localized, and a zh-Hans resource set was created (none existed before). Default-script
|
||
template keys stay untranslated on purpose — they compose the C# comments and script title written
|
||
into the user's <code>.hincproj</code>, which travels to other machines.</li>
|
||
<li><strong>Script faults are keyed errors.</strong> A <code>CompilationErrorException</code> or a faulted script task used to
|
||
surface as an anonymous warning; <a class="xref" href="../api/Hi.SessionCommands.ScriptCommand.html">ScriptCommand</a> now reports
|
||
<code>ScriptCommand-Compile--Failed</code> with the full diagnostic list and <code>ScriptCommand-Run--Fault</code> with the
|
||
exception, both at Error severity.</li>
|
||
<li><strong>A fresh session re-homes the machining chain.</strong> <code>ResetRuntime</code> wrote the configured XYZ home but
|
||
hard-coded ABC to 0, and it only ran on project switch or pace-player reset — never before a plain
|
||
Play. A freshly loaded project therefore started from whatever pose the <code>.mt</code> happened to serialize,
|
||
while the act stream interpolated from the home seed, so the first contour swept from a pose the
|
||
machine was never at and cut along the way. The re-home now reads the rotary homes from the same home
|
||
configuration and also runs at <a class="xref" href="../api/Hi.MachiningProcs.LocalProjectService.html#Hi_MachiningProcs_LocalProjectService_BeginSession_">BeginSession</a>; a
|
||
mid-session replay is untouched.</li>
|
||
<li><strong>What a reset actually resets.</strong> <a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_ResetRuntime_">ResetRuntime</a> now also
|
||
rewinds the NC-runner session state, so the next play restarts file and line indexing from scratch
|
||
the way <code>PowerReset</code> does, and it resets the CL device pose to identity. It no longer clobbers
|
||
<code>MachiningResolution_mm</code>: the runtime resolution is seeded from the workpiece's initial resolution
|
||
only when a project loads, so an explicit override survives a runtime reset and a workpiece swap.</li>
|
||
<li><strong>Mixed runner kinds in one session are refused.</strong> <code>NcRunnerSessionState</code> remembers the runner that
|
||
initialised it and <a class="xref" href="../api/Hi.NcParsers.SoftNcRunner.html#Hi_NcParsers_SoftNcRunner_RunNcLines_">RunNcLines</a> refuses a different one with
|
||
<code>RunNcLines--RunnerMismatch</code> — reachable now that <code>NcKind.Auto</code> makes mixed-kind missions a
|
||
first-class flow.</li>
|
||
<li><strong>Stale state on a chain or project switch.</strong> Building the coordinate converter nulls the rotary
|
||
solver when the chain is not an <code>IXyzabcChain</code>, so a solver built for the old machine no longer keeps
|
||
converting after a switch to a CL device; and
|
||
<a class="xref" href="../api/Hi.NcMech.Workpieces.WorkpieceService.html#Hi_NcMech_Workpieces_WorkpieceService_ClearCache_">ClearCache</a> now also calls
|
||
<a class="xref" href="../api/Hi.NcMech.Workpieces.WorkpieceService.html#Hi_NcMech_Workpieces_WorkpieceService_ClearIdealGeomCache_">ClearIdealGeomCache</a>, so loading another project stops
|
||
rendering the previous project's target geometry.</li>
|
||
<li><strong>Project-file operations are serialized through a zero-wait gate.</strong> A New / Load / Save / Reload
|
||
arriving while another is in progress throws <a class="xref" href="../api/Hi.MachiningProcs.ProjectFileBusyException.html">ProjectFileBusyException</a>
|
||
immediately instead of racing into a file-in-use <code>IOException</code>.</li>
|
||
<li><strong><a class="xref" href="../api/Hi.Machining.MachiningEquipmentUtils.MachiningEquipmentUtil.html#Hi_Machining_MachiningEquipmentUtils_MachiningEquipmentUtil_AlignWorkpieceProgramZeroToIso_">AlignWorkpieceProgramZeroToIso</a>
|
||
computes in the machine-zero state.</strong> It reflects the assembly and zeroes every dynamic axis before
|
||
querying displacements, so the alignment is correct even when the live machine's axes are
|
||
displaced.</li>
|
||
<li><strong><a class="xref" href="../api/Hi.Common.PacePlayer.html#Hi_Common_PacePlayer_RunCount">RunCount</a></strong> counts runs started, incremented synchronously before the
|
||
run's task launches and never reset. Pairing it with <code>IsFinished</code> in one snapshot lets a polling
|
||
client distinguish “the run I started has finished” from a stale Finished left by a previous run.</li>
|
||
</ul>
|
||
<h2 id="geometry-rendering-and-native-stability">Geometry, rendering and native stability</h2>
|
||
<ul>
|
||
<li><strong>Disposing a display or geometry object still in use no longer crashes the process.</strong> A client
|
||
disconnect, a meshed-geometry reset or an app shutdown could take the process down with an access
|
||
violation. <a class="xref" href="../api/Hi.Disp.DispEngine.html">DispEngine</a> and <a class="xref" href="../api/Hi.Cbtr.CubeTree.html">CubeTree</a> native calls are now gated against
|
||
a concurrent dispose, and disposals run serialized on a single background chain —
|
||
<a class="xref" href="../api/Hi.Cbtr.CubeTree.html#Hi_Cbtr_CubeTree_IsDisposed">IsDisposed</a> reports the state and
|
||
<a class="xref" href="../api/Hi.Cbtr.CubeTree.html#Hi_Cbtr_CubeTree_DisposeBackground_">DisposeBackground</a> enqueues a tree, or a collection of its attachments,
|
||
onto that chain.</li>
|
||
<li><strong>Large geometry no longer freezes the UI.</strong> <a class="xref" href="../api/Hi.NcMech.Solids.Solid.html">Solid</a> builds its display
|
||
topology off-thread and draws a wire bounding box with a “Loading” mark until it is ready.</li>
|
||
<li><strong><a class="xref" href="../api/Hi.CutterLocations.ClStrips.ClStrip.html">ClStrip</a> raises a <code>Cleared</code> event after <code>Clear</code></strong>, pairing with
|
||
the existing <code>PosAdded</code>.</li>
|
||
<li><strong>A P/Invoke correctness sweep</strong> reconciled the managed declarations against the real export table.
|
||
It fixed a non-existent export (<code>substraction_ExpandToBox3d</code>), two <code>void</code> natives declared as
|
||
struct returns (a garbage register read), two <code>ToString</code> marshals that made the CLR free foreign
|
||
memory, and a log-callback delegate nothing rooted against GC — native could call a dead thunk long
|
||
after the P/Invoke returned. These are the crashes a user reports as “it crashes randomly”.</li>
|
||
<li><strong>Milled step colours no longer go stale at random.</strong> Step colours are baked into the native cube-tree
|
||
attachment, but the refresh only flagged the strip while the display cache was freed immediately, so a
|
||
frame landing in that window rebuilt the cache from stale colours and nothing cleaned it again. The
|
||
service now cleans the cache once more after the re-stamp. A paired fix stops an empty strip display
|
||
window swallowing a pending recolor indefinitely.</li>
|
||
<li><strong>The dimension bar reads on any background.</strong> It was a single hard-coded near-black stroke left over
|
||
from the light-host era, invisible once the front end went dark. It is now drawn as a wider dark halo
|
||
under a white main stroke, with the halo pushed back whole depth steps rather than the white pass
|
||
nudged forward by half a depth LSB — which intermittently lost the depth test.</li>
|
||
<li><strong>New geometry API.</strong> <a class="xref" href="../api/Hi.Geom.Topo.CarveStl.html">CarveStl</a> is the managed face of the native exact
|
||
triangle-CSG container. <a class="xref" href="../api/Hi.Cbtr.CubeTree.html#Hi_Cbtr_CubeTree_Add_">Add</a> is the boolean-union counterpart of <code>Substract</code>,
|
||
returning <a class="xref" href="../api/Hi.Cbtr.UnmanagedAddition.html">UnmanagedAddition</a>, and <a class="xref" href="../api/Hi.Machining.SweptableUtil.html#Hi_Machining_SweptableUtil_AddBySweepingVolume_">AddBySweepingVolume</a>
|
||
mirrors <code>RemoveBySweepingVolume</code> — the geometry-layer symmetric point for additive processes. There is
|
||
no deposition step in the machining runner yet, so this is a geometry-level API only.</li>
|
||
<li><strong><a class="xref" href="../api/Hi.Milling.FluteContours.FreeformBottomContour.html">FreeformBottomContour</a></strong> is the user-editable point-list bottom
|
||
contour, mirroring the side contour with the key axis switched to radius.</li>
|
||
</ul>
|
||
<h2 id="performance-and-footprint">Performance and footprint</h2>
|
||
<p>Every figure below is a measurement with its conditions stated, and where a change cost time to buy
|
||
correctness that is said too. Read the ratios rather than the absolute times: several campaigns were
|
||
run on Debug builds or on small machines, deliberately, because a paired A/B on one machine answers
|
||
“did this get faster” far more reliably than an unpaired Release number on a fast one.</p>
|
||
<h3 id="milling-physics-in-the-native-kernel">Milling physics in the native kernel</h3>
|
||
<p>The per-step physics moved into <code>core.dll</code> in stages — engagement scan conversion, the force kernel,
|
||
then the sequential temperature and wear chain. Measured as a same-day paired A/B, managed leg
|
||
against native leg, on one circular test program:</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Per touched step</th>
|
||
<th>managed</th>
|
||
<th>native</th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Engagement build</td>
|
||
<td>46.0 ms</td>
|
||
<td><strong>5.03 ms</strong></td>
|
||
<td>~9×</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Force (<code>GetMillingFoce</code>)</td>
|
||
<td>17.1 ms</td>
|
||
<td><strong>0.75 ms</strong></td>
|
||
<td>~20×</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Temperature and wear chain</td>
|
||
<td>3.97 ms</td>
|
||
<td><strong>0.24 ms</strong></td>
|
||
<td>~16×</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>Whole play</strong></td>
|
||
<td><strong>59.3 s / 16.1 GB allocated</strong></td>
|
||
<td><strong>40.6 s / 3.4 GB allocated</strong></td>
|
||
<td>−32% wall, −79% allocation</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Allocation is where the migration bites hardest: engagement construction alone fell from about
|
||
5.2 GB to 29 MB per step.</p>
|
||
<blockquote>
|
||
<p><strong>Conditions.</strong> Debug x64, <code>EnablePhysics</code> on, collision off, one force worker, a two-core /
|
||
four-thread laptop, ±10% thermal-throttle noise, single paired run per leg. Absolute times are not
|
||
representative of a customer machine — the ratios are the claim.</p>
|
||
</blockquote>
|
||
<blockquote>
|
||
<p><strong>Numerical parity.</strong> Engagement, force and brief are bit-identical between the two legs <strong>on
|
||
Windows</strong>. The Linux build is not bit-identical (different libm), so a cross-platform comparison
|
||
should use a tolerance, not equality.</p>
|
||
</blockquote>
|
||
<h3 id="playing-a-long-program-stays-linear">Playing a long program stays linear</h3>
|
||
<p><code>NcOptOption.Equals</code> ended on a null-propagating comparison of a dictionary that is created on
|
||
demand and is null on virtually every option, so the whole comparison collapsed to <code>false</code> — an
|
||
option compared unequal even to a copy of itself. Both record-on-change guards built on it were
|
||
therefore dead: the session appended an option-map entry for <strong>every played act</strong> instead of only at
|
||
change points, and the step rewrote unchanged entries. Reading the last recorded option through a
|
||
LINQ <code>LastOrDefault</code> over a <code>SortedList<,></code> — which has no indexed fast path — then walked the whole
|
||
map each time, so the two defects together made a long play quadratic.</p>
|
||
<blockquote>
|
||
<p>Measured on a 2.35-million-line Siemens program: the option map now holds <strong>1 entry instead of one
|
||
per line</strong>, and the per-100,000-line rate stays <strong>flat</strong> instead of degrading from 73 s at the
|
||
start of the file to about 11 minutes by 1.9 million lines.</p>
|
||
</blockquote>
|
||
<p>This applies to <strong>every</strong> runner and to sessions doing no optimization at all, because the call site
|
||
is the session-level play loop. <code>GetHashCode</code> drops the dictionary in the same change, since it
|
||
hashed by reference and would otherwise disagree with <code>Equals</code> — relevant if you use <code>NcOptOption</code>
|
||
as a dictionary key.</p>
|
||
<h3 id="where-the-time-actually-goes">Where the time actually goes</h3>
|
||
<p>Worth knowing before you tune anything. After the migration, on the measured workload the <strong>whole
|
||
parallel physics stage is about 3.3% of wall time</strong>, while the <strong>single-worker volume subtraction is
|
||
about 77%</strong> — and that subtraction is single-worker as a correctness requirement, not as an
|
||
oversight. Raising the force-worker count therefore buys nothing on any machine; the bottleneck
|
||
moved rather than disappearing.</p>
|
||
<p>What did change in the worker derivation is narrower than it sounds. An unmeasured six-core ceiling
|
||
was removed, but it only ever governed the sweep workers, and only machines with <strong>nine or more
|
||
logical processors</strong> see a different count; force workers are unchanged everywhere. The throughput
|
||
benefit on such a machine has <strong>not</strong> been measured — the development machines are smaller — so this
|
||
is a ceiling removal, not a claimed speedup.</p>
|
||
<p>Queue depths became fixed item budgets (120 geometry, 3840 physics) rather than scaling with the core
|
||
count, because those queues bound per-item memory: uncapped, a 64-core machine would have been handed
|
||
40,960-deep physics queues. On machines with fewer than six cores this is a small <em>increase</em> in
|
||
bounded-queue memory (from 80 / 2560), which is the honest cost of the change.</p>
|
||
<h3 id="loading-a-large-stl-workpiece">Loading a large STL workpiece</h3>
|
||
<p>Building the topology from an STL was quadratic in triangle count — a pointer-derived hash collapsed
|
||
into a handful of buckets, so lookups degenerated into linear scans. On one 935,000-triangle binary
|
||
STL, topology construction was <strong>99.6%</strong> of the entire load; reading the file off disk was 0.16% of
|
||
it. With a multiplicative hash mix the build is linear:</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Triangles</th>
|
||
<th>before</th>
|
||
<th>after</th>
|
||
<th></th>
|
||
<th>worst bucket</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>100,000</td>
|
||
<td>8,711 ms</td>
|
||
<td><strong>1,305 ms</strong></td>
|
||
<td>6.7×</td>
|
||
<td>2,245 → 21</td>
|
||
</tr>
|
||
<tr>
|
||
<td>300,000</td>
|
||
<td>89,036 ms</td>
|
||
<td><strong>4,750 ms</strong></td>
|
||
<td>18.7×</td>
|
||
<td>6,593 → 23</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Per-triangle cost is now flat (0.013 → 0.016 ms/tri across a 3× size increase), which is the real
|
||
result: the cost grows with the mesh instead of with its square. Extrapolated to the full
|
||
935,000-triangle mesh that is roughly <strong>14 minutes → 15 seconds</strong>.</p>
|
||
<p>Deduplication and the resulting topology are unchanged — the equality predicate was not touched, and
|
||
the 300,000-triangle case produces an identical 899,997 lines before and after. Separately, the
|
||
managed-to-native STL handoff dropped from three full copies of the buffer (about 86 MB each, plus
|
||
around twenty doubling reallocations) to two.</p>
|
||
<blockquote>
|
||
<p><strong>Conditions.</strong> Native test harness, debug CRT — which inflates container-operation constants, so
|
||
the absolute milliseconds are an upper bound. The composition breakdown and the complexity change
|
||
are build-configuration independent. The full-mesh figure is an extrapolation, not a measured run.</p>
|
||
</blockquote>
|
||
<h3 id="re-triangulating-after-a-cut">Re-triangulating after a cut</h3>
|
||
<p>The marching-cubes step gained a lookup table, and produces fewer triangles for the same surface:</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Tree</th>
|
||
<th>before</th>
|
||
<th>after</th>
|
||
<th></th>
|
||
<th>triangles</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>17 MB diagnostic</td>
|
||
<td>0.63 s</td>
|
||
<td>0.29 s</td>
|
||
<td>2.17×</td>
|
||
<td>−35%</td>
|
||
</tr>
|
||
<tr>
|
||
<td>30 MB demo</td>
|
||
<td>1.29 s</td>
|
||
<td>0.60 s</td>
|
||
<td>2.15×</td>
|
||
<td>−35%</td>
|
||
</tr>
|
||
<tr>
|
||
<td><strong>309 MB customer part</strong></td>
|
||
<td><strong>14.68 s</strong></td>
|
||
<td><strong>6.51 s</strong></td>
|
||
<td><strong>2.25×</strong></td>
|
||
<td><strong>−43%</strong></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<blockquote>
|
||
<p><strong>Scope.</strong> This lands on the rebuild burst after a cut invalidates cached geometry, <strong>not</strong> on
|
||
steady-state rendering, which draws from the display cache and is unchanged.</p>
|
||
</blockquote>
|
||
<p>It is also an approximation change, not purely a speedup: a non-finite cut drops its triangles, so a
|
||
sub-voxel feature vanishes at that level of detail instead of being capped. That is what fixed the
|
||
broken-face slabs seen on RTCP paths. The contact-loop extraction used by milling physics
|
||
deliberately still uses the previous walk, so physics results are untouched.</p>
|
||
<h3 id="session-memory-a-long-program-no-longer-exhausts-the-client">Session memory: a long program no longer exhausts the client</h3>
|
||
<p>A session retains every executed NC block for its whole lifetime. Once a block leaves the executing
|
||
window its piece is now frozen to compact UTF-8.</p>
|
||
<blockquote>
|
||
<p>Measured on a 25,018-block play: <strong>session retention 406 MB → 142 MB</strong>, about 2.9×.</p>
|
||
</blockquote>
|
||
<p>The encoding itself is smaller than that ratio suggests — roughly 12 KB per line live against 1.6 KB
|
||
frozen, about 12.9× — because a retained piece carries more than its JSON. The 2.9× is the figure
|
||
that matters for whether a program fits in memory.</p>
|
||
<p>The trade is explicit: after the freeze the <code>JsonObject</code> getter re-parses on every call and returns a
|
||
fresh read-only snapshot, with no caching and no write-back. Code that reads the same piece
|
||
repeatedly should hold the snapshot in a local. The switch is
|
||
<a class="xref" href="../api/Hi.MachiningProcs.NcRunnerSessionState.html#Hi_MachiningProcs_NcRunnerSessionState_FreezeExecutedPieces">FreezeExecutedPieces</a>, on by default.</p>
|
||
<h3 id="sizing-a-meshed-workpiece">Sizing a meshed workpiece</h3>
|
||
<p>A cube tree costs roughly <strong>3.2× its file size in RAM</strong> while loaded — a 10 GB <code>.wct</code> at 0.125 mm
|
||
resolution is about 95 million nodes, holding around 25 GB of tree plus 6 GB of index. Tearing down a
|
||
tree that size used to block the caller for over two minutes; disposal now runs serialized on a
|
||
background chain, so the thread that dropped it does not wait. The remaining cost is genuine work:
|
||
the live renderer must not be left showing geometry that no longer exists.</p>
|
||
<h3 id="cutter-location-files-at-production-scale">Cutter-location files at production scale</h3>
|
||
<p>Three costs were removed from the CL-to-machine path, and on a production-scale file they are the
|
||
difference between replaying and appearing to hang: tool-offset resolution walked back to the distant
|
||
<code>LOAD</code> block for every motion (O(N²), now O(1) through a modal section), the documentary
|
||
program-to-Pn stamp did the same walk (now stamped once per run), and the program-zero query
|
||
deep-cloned the whole equipment assembly on every motion block (now a cached per-run matrix over the
|
||
live assembly). These are complexity changes; they have not been separately timed.</p>
|
||
<h3 id="smaller-footprint">Smaller footprint</h3>
|
||
<p>The embedded default font is handed to the display engine from memory, so an <strong>11 MB</strong> <code>.ttf</code> is no
|
||
longer written into the process working directory on startup. The packages are x64-only, and
|
||
HiNc-Resource no longer ships a duplicated nested copy of the CT-350 STL set.</p>
|
||
<h3 id="things-that-cost-more-on-purpose">Things that cost more, on purpose</h3>
|
||
<p><strong>Five-axis inverse kinematics.</strong> Tightening the orientation envelope from about 1.4e-3 rad to about
|
||
1e-6 rad — measured maxima 1.5e-8 rad on the hot path and 2.1e-8 on teleport, a tip deviation of
|
||
0.05 µm on a 50 mm tool — costs roughly eleven solver iterations where one used to do, so a
|
||
posture-changing call went from about 23 µs to about 251 µs, and a teleport from 418 µs to 1607 µs.
|
||
Only posture-changing RTCP and arc steps pay it: three-axis programs and constant-posture segments
|
||
are exempt through the <code>McLinear</code> downgrade. In absolute terms a 1,432-step five-axis replay spends
|
||
about 0.36 s in the solver. (Debug build including measurement overhead, so those microseconds are an
|
||
upper bound.)</p>
|
||
<p><strong>Machine-coordinate linear stepping.</strong> <a class="xref" href="../api/Hi.Numerical.Acts.ActMcXyzLinearContour.html">ActMcXyzLinearContour</a> derives its
|
||
step count from the <strong>euclidean</strong> length of the machine XYZ delta rather than the largest single-axis
|
||
component, so <code>LinearResolution_mm</code> caps actual tool-tip travel per step. A diagonal move therefore
|
||
produces up to √3× more steps than before at the same setting — more work, for a sampling density
|
||
that now means what the setting says. Lower the resolution if the old step count was what you were
|
||
budgeting for.</p>
|
||
<h3 id="a-tuning-cliff-worth-knowing-about">A tuning cliff worth knowing about</h3>
|
||
<p><code>MillingCycleDivisionNum</code> saturates. Raising it past roughly 180 buys no additional training accuracy
|
||
while the cost keeps climbing: a training run that takes about four minutes at 180 takes hours at 720
|
||
and needs on the order of 100 GB of RAM to do it. The default of 36 is for ordinary simulation; raise
|
||
it for training, but not past the point where the curve flattens.</p>
|
||
<h2 id="packaging-resources-and-hosting">Packaging, resources and hosting</h2>
|
||
<ul>
|
||
<li><strong>Shipped resources carry an ownership marker.</strong> <a class="xref" href="../api/Hi.Common.ResourceDefaultMarker.html">ResourceDefaultMarker</a> introduces the
|
||
<code>.default</code> convention: files carry the marker before the final extension
|
||
(<code>AlTiBN.default.CoatingMaterial</code>) and machine-tool packages carry it on the folder
|
||
(<code>MachineTool/Table-B1.default/</code>). Marked items are system territory the seeder may refresh or delete;
|
||
unmarked items belong to the user and are never touched. <a class="xref" href="../api/Hi.HiNcKits.ResourceSeeder.html#Hi_HiNcKits_ResourceSeeder_Seed_">Seed</a>
|
||
copies the shipped defaults into the admin resource root at startup — anchored on the application base
|
||
directory rather than the process working directory, version-stamped so steady-state boots do no work.
|
||
A save-as flow must strip the marker so a user file cannot masquerade as a shipped default.</li>
|
||
<li><strong>HiNc-Resource ships more presets</strong>: <code>Resource/Controller/<Brand>.default.Controller</code> for all five
|
||
brands, and <code>StandardForcedAir</code> / <code>StandardWaterSolubleCoolant</code> / <code>StandardOilBasedCoolant</code> coolant
|
||
conditions, so those load browsers start populated instead of empty.</li>
|
||
<li><strong><a class="xref" href="../api/Hi.Physics.CoolantHeatCondition.html">CoolantHeatCondition</a></strong> gains name/note, the three static presets, preset
|
||
find/match/apply, and side-file IO following the workpiece-material pattern —
|
||
<a class="xref" href="../api/Hi.Machining.MachiningEquipmentUtils.MachiningEquipment.html#Hi_Machining_MachiningEquipmentUtils_MachiningEquipment_CoolantHeatConditionFile">CoolantHeatConditionFile</a> externalizes
|
||
the condition to a <code>.CoolantHeatCondition</code> file.</li>
|
||
<li><strong>Obfuscation-safe DTOs.</strong> Obfuscar renames compiler-generated anonymous types and strips their
|
||
constructor parameter names, so <code>System.Text.Json</code> threw on every <code>ToPresentDto</code> serialization in
|
||
released assemblies — the geometry, cutter and transformer editors all returned HTTP 500 while Debug
|
||
builds were fine. Every implementation now returns <code>Dictionary<string, object></code> with <code>nameof</code> keys,
|
||
which compile to string literals obfuscation cannot touch, and
|
||
<a class="xref" href="../api/Hi.Common.IToPresentDto.html">IToPresentDto</a> documents the rule. See the wire-key list under
|
||
<a href="#7-signature-and-shape-changes">Signature and shape changes</a>.</li>
|
||
<li><strong>The embedded default font is Noto Sans CJK TC</strong> (SIL OFL 1.1) in place of the Big5-only HanWang
|
||
WCL06, fed to the native engine from memory instead of writing an 11 MB <code>Font/WCL06.ttf</code> into the
|
||
process working directory. Traditional, simplified and kana render from one face with zh-Hant glyph
|
||
conventions. Explicit font paths still go through the file route.</li>
|
||
<li><strong>Third-party notices</strong> ship with the two packages that actually redistribute third-party bits: HiDisp
|
||
(the native files under <code>runtimes/</code> and the embedded font) and HiNc-Resource (the offline
|
||
documentation site among its content files). HiLicense gained a real package description.</li>
|
||
<li><strong>Dependency updates</strong> — <code>SQLitePCLRaw.bundle_e_sqlite3</code> is pinned to 3.0.3 (SQLite
|
||
CVE-2025-6965), <code>Microsoft.Data.Sqlite</code> to 10.0.9 and <code>Dapper</code> to 2.1.79.</li>
|
||
<li><strong>Small public additions</strong> — <a class="xref" href="../api/Hi.Common.FileLines.FileUtil.html#Hi_Common_FileLines_FileUtil_DetectRoundTripEncoding_">DetectRoundTripEncoding</a>,
|
||
<a class="xref" href="../api/Hi.Common.JsonUtil.html#Hi_Common_JsonUtil_CompactNanOptions">CompactNanOptions</a> and named float literals in
|
||
<a class="xref" href="../api/Hi.Common.JsonUtil.html#Hi_Common_JsonUtil_GetDouble_">GetDouble</a>, <a class="xref" href="../api/Hi.Geom.MathUtil.html#Hi_Geom_MathUtil_CycleUpperInclusive_">CycleUpperInclusive</a> (the <code>(l,u]</code>
|
||
cyclic window the existing overloads could not express), and
|
||
<a class="xref" href="../api/Hi.Common.Collections.SynList-1.html#Hi_Common_Collections_SynList_1_AddAndGetIndex_">AddAndGetIndex</a>. <a class="xref" href="../api/Hi.Common.IndexSegment.html">IndexSegment</a> no longer leaves
|
||
an open run end when the match sits at either edge of the list.</li>
|
||
</ul>
|
||
<h2 id="new-diagnostics-you-may-now-see">New diagnostics you may now see</h2>
|
||
<p>Several failure modes that used to be silent now report. These ids are searchable and filterable —
|
||
they are the fastest way to find out what a run actually did.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Id</th>
|
||
<th>Means</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>Play-Touch--None</code></td>
|
||
<td>the play finished without any step touching the workpiece</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Play-Physics--None</code></td>
|
||
<td>physics is on and steps touched, but no touched step carries a physics brief</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Tool-FluteCount--Zero</code></td>
|
||
<td>physics is on and a milling cutter resolves to zero flutes</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SpindleDirection--AssumedCw</code></td>
|
||
<td>an S word greater than zero with no direction ever issued</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Composition--NotLicensed</code></td>
|
||
<td>external pipeline units were skipped for this session</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Script--NotLicensed</code></td>
|
||
<td>an NC-embedded C# script was skipped</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SiemensToolOffset--TcdpRowMissing</code></td>
|
||
<td>a Siemens (T, D) pair had no <code>$TC_DP</code> row; the generic tool height was used</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Comp-ToolHeight--001</code></td>
|
||
<td>a G43.4 H word could not be resolved</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Coord-MachCoord--005</code> / <code>--006</code> / <code>--007</code></td>
|
||
<td>a G53 or G53.1 machine-coordinate move failed on a path that used to fail silently</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Coord-Tilt--001</code> / <code>--002</code></td>
|
||
<td>a G68.2 tilted plane the machine cannot reach</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>BuildNcLines--ParseFailed</code></td>
|
||
<td>a line could not be parsed; it survives verbatim but is not simulated</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>RunNcLines--RunnerMismatch</code></td>
|
||
<td>a second runner kind was attempted inside one session</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ReadNcRunnerSuit--Refused</code></td>
|
||
<td>a suit switch was attempted while a program was playing</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>PostExecution--MeshedGeomOutputRetired</code></td>
|
||
<td>an old project still carries the retired meshed-geom output pair</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ConvertClToNc--NoPlay</code></td>
|
||
<td>CL-to-NC conversion ran with no prior play on a machine chain</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ClToMc--NoToolOffset</code></td>
|
||
<td>a CL motion resolved no tool offset</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Map-ShotGap--StepsSkipped</code></td>
|
||
<td>steps were skipped because their shot pairing window held no measured row</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Train-StepEngagement--Missing</code></td>
|
||
<td>a step's row is present but its engagement was never built</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Train-StepLuggage--Unreadable</code></td>
|
||
<td>a step's luggage row could not be read back</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Writeback-Patch--*</code></td>
|
||
<td>a writeback edit refused a variable, keyword or comment-only value, or matched nothing</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>HeidenhainPlane--Unsupported</code> / <code>SiemensFrame--Unsupported</code> / <code>HeidenhainCycl--Unsupported</code></td>
|
||
<td>the construct is recognized and consumed safely, but not simulated</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DeclaredMCode--UnmodeledEffects</code></td>
|
||
<td>a machine-declared OEM M-code occurred; no effects are simulated for it</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
</article>
|
||
|
||
<div class="contribution d-print-none">
|
||
</div>
|
||
|
||
<div class="next-article d-print-none border-top" id="nextArticle"></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>
|