This repository has been archived on 2026-10-11. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
HiNC-2025-win-desktop-Deploy/App/wwwroot/HiAPI-docsite/anatomy/general-setup/controller/program-data/frames.html
T
2026-09-09 17:35:23 +08:00

509 lines
34 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Frames | HiAPI-C# 2025 </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Frames | 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 &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../../../../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<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="Anatomy-ControllerFrames">
<h1 id="frames">Frames</h1>
<p>Frames is the Controller branch's Sinumerik settable-frame ledger: one row per <code>$P_UIFR</code> entry,
each carrying the X / Y / Z translation HiNC stores for that frame. It lives on the General Setup
page at <code>/general-setup</code> under the Control-Tree id <code>equipment/controller/program-data/frames</code>,
reached as <code>?tree=equipment/controller/program-data/frames</code>, and it is grown only while the active
runner resolves a Siemens frame table — among the shipped brand presets, Siemens alone. That same
table is the offset provider behind the ungated <strong>Work Coordinates (G54…)</strong> leaf on this brand, so
the two nodes edit one object.</p>
<div class="IMPORTANT">
<h5>Important</h5>
<p>Anatomy makes no claim that any id named here is stable across versions. The migration hop that
keeps an older <code>?tree=</code> value resolving is described in
<a class="xref" href="../../../platform/tree-ids-and-routes.html">Tree Ids and Routes</a>.</p>
</div>
<h2 id="what-a-frame-is-here">What a Frame Is Here</h2>
<p>On a Sinumerik, <code>$P_UIFR</code> is an array of frames and each entry carries a translation, a rotation, a
scale and a mirror. HiNC consumes the translation and nothing else, so
<a class="xref" href="../../../../api/Hi.NcParsers.Dependencys.Siemens.SiemensFrameTable.html">SiemensFrameTable</a> stores one <a class="xref" href="../../../../api/Hi.Geom.Vec3d.html">Vec3d</a> per frame
id in <a class="xref" href="../../../../api/Hi.NcParsers.Dependencys.Siemens.SiemensFrameTable.html#Hi_NcParsers_Dependencys_Siemens_SiemensFrameTable_Frames">Frames</a>, with a second,
axis-letter-keyed dictionary beside it for translation components on axes other than X, Y and Z.</p>
<p>The table is a dependency in its own right rather than a section of the machine data, because
<code>$P_UIFR</code> is not machine data on the control either:
<a class="xref" href="../../../../api/Hi.NcParsers.Dependencys.Siemens.SiemensMachineDataTable.html">SiemensMachineDataTable</a> holds the <code>MD</code>-numbered parameters
— axis type, reference position, stroke limits — and carries no frame. That split is also why the
frame table is the brand's ISO offset provider while the machine-data table is not.</p>
<p>The array index is not the row key. Rows are keyed by the G-code that selects the frame, and the
bridge that serves <code>$P_UIFR</code> accesses maps one onto the other:</p>
<table>
<thead>
<tr>
<th><code>$P_UIFR</code> index</th>
<th>Frame id</th>
<th>Row on this leaf</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>0</code></td>
<td><code>G500</code></td>
<td>none — the cancel frame is never stored</td>
</tr>
<tr>
<td><code>1</code>–<code>4</code></td>
<td><code>G54</code>–<code>G57</code></td>
<td>the four base rows</td>
</tr>
<tr>
<td><code>5</code>–<code>99</code></td>
<td><code>G505</code>–<code>G599</code></td>
<td>the extended tail</td>
</tr>
</tbody>
</table>
<p>An index outside <code>0</code>–<code>99</code> maps to no id at all, and the bridge drops the access rather than
inventing a frame for it.</p>
<h3 id="settable-and-computed">Settable, and computed</h3>
<p>Four parts of the Sinumerik frame chain show up in this branch's behaviour, and only one of them is
a row here.</p>
<ul>
<li><strong>The settable frames</strong> are the table. Ninety-nine ids are allocated by the constructor —
<code>G54</code>–<code>G57</code> plus every id in
<a class="xref" href="../../../../api/Hi.NcParsers.Keywords.Siemens.SiemensKeywords.html#Hi_NcParsers_Keywords_Siemens_SiemensKeywords_ExtendedCoordinateSeries">ExtendedCoordinateSeries</a>, which is
<code>G505</code> through <code>G599</code> — each seeded to zero, matching a control where every <code>$P_UIFR[n]</code> is
allocated with an initial value of zero. Every one is editable on this leaf.</li>
<li><strong><code>G500</code></strong> is computed, not stored. The accessor answers a zero offset for it and drops a write,
and the constructor deliberately keeps it out of the dictionary, so it is a row on neither this
leaf nor Work Coordinates. The description above the table says as much: <em>&quot;Settable frames
($P_UIFR, translation only); G500 cancels and stores nothing.&quot;</em></li>
<li><strong>The programmable frame</strong> — <code>TRANS</code> / <code>ATRANS</code> / <code>ROT</code> / <code>AROT</code> and their solid-angle forms,
together with the <code>CYCLE800</code> tilt that shares its slot — is computed per block from the program
and has no table, no node and no stored value anywhere in this branch.</li>
<li><strong>A frame's rotation and fine-offset components</strong> reach neither this table nor the simulation. Only
the <code>TR</code> component of a <code>$P_UIFR</code> access is bridged into the frame entry; a write to any other
component is recorded on the block and reported as recognised-but-not-simulated by the Siemens
system-variable catch-all.</li>
</ul>
<h2 id="how-the-chain-composes">How the Chain Composes</h2>
<p>A frame word in a program selects one id. The Siemens coordinate syntax resolves that id's offset
through <a class="xref" href="../../../../api/Hi.NcParsers.SoftNcRunner.html#Hi_NcParsers_SoftNcRunner_GetEffectiveNcDependencyList_">GetEffectiveNcDependencyList</a><small>(API)</small>, taking
the first provider that answers, and writes the result twice: as the block's coordinate-offset
section, and as one named entry in the block's program-to-machine transform chain. Entries in that
chain are multiplied in the order they were written, so slot order is the whole of the composition
rule.</p>
<p>Two placements in the Siemens syntax list decide what a settable frame ends up doing.</p>
<ul>
<li><strong>The programmable-frame entry is written first, deliberately.</strong> The tilt and programmable-frame
syntaxes run ahead of the coordinate-offset syntaxes so their shared entry lands ahead of the
settable frame's. That is what keeps a <code>ROT</code> turning the program coordinates <em>inside</em> the frame
rather than turning the frame's own offset with them. Tool-height compensation is written between
the two, and the kinematic pivot transform is written last so every frame-space operation is
accumulated before the final inverse kinematics.</li>
<li><strong>Both coordinate syntaxes are registered, and they share one entry.</strong> The Siemens preset carries
the ISO coordinate syntax and the Siemens one side by side; each writes the chain entry under the
same name, and a repeated name is replaced in place rather than appended. So the <code>G54</code>–<code>G59</code>
vocabulary the ISO syntax recognises and the <code>G500</code> and <code>G505</code>–<code>G599</code> vocabulary the Siemens one
adds resolve into a single slot. The Siemens syntax leaves the coordinate flag in place instead of
consuming it, and falls back to the block's existing coordinate section and then to the previous
block's, which is what carries a frame selection modally.</li>
</ul>
<p>Three codes bypass the composed transform for one block rather than changing it: <code>G53</code>, <code>G153</code> and
<code>SUPA</code> all reduce to the same one-shot machine-coordinate move, and the values on this leaf take no
part in such a block.</p>
<p>The word vocabulary is also wider than the table. The ISO syntax's own series adds <code>G58</code>, <code>G59</code> and
<code>G59.1</code>–<code>G59.9</code>, none of which the frame table allocates; such a word resolves to no offset from any
provider and composes a zero translation.</p>
<h2 id="the-rows-and-the-columns">The Rows and the Columns</h2>
<p>The panel is a four-column table and nothing else — no toolbar, no add footer, no action column, no
dialog. The <strong>Frame</strong> header is translated; <code>X (mm)</code>, <code>Y (mm)</code> and <code>Z (mm)</code> are literals in the
template and stay English under any locale. The id cell is bold plain text and cannot be edited.</p>
<p><strong>The row set is fixed.</strong> The branch exposes exactly two frame routes, a whole-table read and a
per-id write; no third route adds, deletes or resets a row. The write itself is an unguarded
assignment by key rather than an update of an existing row, so an id the table has never held would
be seated as a new one — but no panel has a way to send such an id. A row exists because the table
allocated it, and the ninety-nine allocated ids are the same ninety-nine whatever a project has done
to their values.</p>
<p><strong>Nothing in the path sorts.</strong> The reader projects the dictionary as it enumerates it and applies no
ordering, unlike the datum, retained-variable, R-parameter and tool-offset readers beside it, and the
panel adds none of its own. What that yields depends on how the table was built. A table the proxy
has just created lists <code>G54</code>–<code>G57</code> first and then the extended tail, in construction order. A table
read back from a project file lists the ids in the order the file names them — and the file is
written sorted by id as text, not as a number. Plain string order puts <code>G505</code> ahead of <code>G54</code>, because
the third character decides that pair, and <code>G54</code> ahead of <code>G540</code>, because the shorter of two strings
that share a prefix comes first. So a saved and reopened table does not push the four base frames to
either end: it interleaves them into the extended tail, as <code>G505</code>–<code>G539</code>, <code>G54</code>, <code>G540</code>–<code>G549</code>,
<code>G55</code>, <code>G550</code>–<code>G559</code>, <code>G56</code>, <code>G560</code>–<code>G569</code>, <code>G57</code>, then <code>G570</code>–<code>G599</code>. Work Coordinates enumerates
the same dictionary, so both leaves reorder together.</p>
<h3 id="show-all">Show all</h3>
<p>A <strong>Show all</strong> toggle sits at the right of the header strip. With it off, a row is listed only when
its id matches <code>G54</code> through <code>G57</code>, or when at least one of its three values is non-zero; with it on,
every allocated id is listed. The test is the panel's own regular expression, evaluated in the
browser over the rows the read returned — nothing about it reaches the server, and the toggle is a
plain local flag that returns to off whenever the panel is remounted.</p>
<p>Two details of that rule are worth reading against the sibling leaf. The toggle here is
unconditional, so it renders even on a table with no extended rows at all. And the always-visible
test here is narrower than the work-coordinate one, which admits <code>G54</code> through <code>G59</code> and any of them
followed by a dot and one further digit. On the seeded table the two tests keep the same four rows
visible, because the frame table allocates none of the ids where they differ.</p>
<h2 id="two-nodes-one-table">Two Nodes, One Table</h2>
<div class="WARNING">
<h5>Warning</h5>
<p>On Siemens this leaf and <strong>Work Coordinates (G54…)</strong> are two faces of one instance, not two tables
kept in step. The work-coordinate leaf resolves the first
<a class="xref" href="../../../../api/Hi.NcParsers.Dependencys.IIsoCoordinateConfig.html">IIsoCoordinateConfig</a> on the active runner; on this brand that is
the frame table, because it is the only dependency the Siemens preset carries that implements that
interface — the machine-data table included. A <code>G54</code> edit made on either node is the same
assignment into the same cell.</p>
</div>
<p>This is the reciprocal half of the warning <a class="xref" href="work-coordinates.html">Work Coordinates</a>
carries. What the two leaves share, exactly:</p>
<ul>
<li><strong>The row set.</strong> The work-coordinate reader enumerates the provider's own ids, which for this
provider is the frame dictionary's key set. The two leaves therefore list the same ids in the same
order, and gain or lose none independently.</li>
<li><strong>The X, Y and Z cells.</strong> Both leaves write the whole triad for one id, and both land in the same
dictionary entry. Neither mutates the vector already sitting there: each write installs a fresh
<a class="xref" href="../../../../api/Hi.Geom.Vec3d.html">Vec3d</a> over it, so a reference taken before the write still reads the old values. A
value typed on one leaf is what the other shows at its next mount.</li>
<li><strong>The absence of <code>G500</code>.</strong> Neither leaf can show it, for the same reason: it is not in the
dictionary the ids are enumerated from.</li>
</ul>
<p>What is not shared, and what a reader must not infer from the shared face:</p>
<ul>
<li><strong>The per-axis translation components.</strong> A settable frame's translation on an axis letter other
than X, Y or Z lives in the table's second dictionary, written and read only by the <code>$P_UIFR</code>
bridge. Neither leaf returns it, and neither leaf disturbs it: both write a fresh
<a class="xref" href="../../../../api/Hi.Geom.Vec3d.html">Vec3d</a> into the frame entry and leave the axis dictionary untouched, so a C-axis
frame component set by a program survives every edit made from either panel.</li>
<li><strong>The row actions.</strong> The <strong>P0</strong> and <strong>M0</strong> buttons and the canvas marker belong to Work
Coordinates. This leaf has no action column at all — but P0 and M0 write through the same provider,
so pressing one there changes what this leaf shows.</li>
<li><strong>The presence gate.</strong> This leaf gates on the concrete frame table; the other gates on the ISO
interface. On Siemens the two answers are one object and the leaves appear together; the empty
lines they would show differ all the same — <em>&quot;No Siemens frame table on the active runner.&quot;</em> here,
<em>&quot;No work-coordinate table on the active runner.&quot;</em> there.</li>
<li><strong>The write path.</strong> The work-coordinate route writes through the provider's coordinate accessor,
which drops a <code>G500</code> write; the frame route assigns into the dictionary by key and would store one.
Neither is reachable from a panel, because both panels only ever send an id their own read
returned.</li>
<li><strong>The caption.</strong> Work Coordinates picks its caption from the snapshot's coordinate-kind field and
on this brand shows <em>&quot;Stored as Siemens settable frames ($P_UIFR; G500 cancels and is always
zero).&quot;</em> — which is that leaf naming this one. This leaf's caption is fixed.</li>
</ul>
<p>Nothing reconciles the two views while both are in scope, and nothing needs to: the editor row mounts
one panel at a time and each fetches once on mount, so moving the selection between the two nodes is
itself the refresh. What a panel that stays mounted therefore never sees is described in
<a class="xref" href="../editing-contract.html">Editing Contract</a>.</p>
<h2 id="editing-a-frame">Editing a Frame</h2>
<p>Every value cell is the shared numeric field, so it commits on blur or on Enter and never per
keystroke; its parsing, its bounds behaviour and the second commit that follows Enter are
<a class="xref" href="../../../widget/numeric-input.html">Numeric Input</a>. No cell here passes a minimum or a maximum, and no cell
carries a unit suffix — the millimetre is stated in the column header instead.</p>
<p><strong>The write is the whole row.</strong> A commit assigns the new number into the local row and sends that
row's <code>x</code>, <code>y</code> and <code>z</code> as they now stand under the row's id. The optimistic shape, the single-cell
rollback and the toast a failure raises are the branch's own and are described in the
<a class="xref" href="../editing-contract.html">Editing Contract</a>; what is this panel's is the guard in
front of them. The numeric field can emit an empty value as null and the literals <code>Infinity</code>,
<code>-Infinity</code> and <code>NaN</code> as non-finite numbers, and the handler returns before the request on all four.
So a cleared cell stores nothing and clears nothing: the box shows blank while the stored number
stands, and the number returns when the panel is remounted by selecting another node and coming back.</p>
<p>No surface here renames a frame: the id is the write's route key and no route accepts a replacement
for it. The panel reports no structural change either, so no edit on this leaf rebuilds the branch.</p>
<h2 id="what-survives-and-what-a-brand-change-destroys">What Survives, and What a Brand Change Destroys</h2>
<p>The table is per-case: <a class="xref" href="../../../../api/Hi.NcParsers.Dependencys.Siemens.SiemensFrameTableProxy.html">SiemensFrameTableProxy</a> stands in the
runner's pipeline list and the real table lives on the project's
<a class="xref" href="../../../../api/Hi.NcParsers.NcRunnerSuit.html#Hi_NcParsers_NcRunnerSuit_PerCaseNcDependencyList">PerCaseNcDependencyList</a>, serialized inside the project file. That
proxy carries <strong>no seed</strong> — it installs a freshly constructed table when the project holds none and
takes the project's own table thereafter — so the runner file records only the placeholder, and a
<code>.Controller</code> written from this project carries no frame values at all. The ownership rules the
proxy pattern follows across the branch are <a class="xref" href="index.html">Program Data</a>.</p>
<p>Two consequences follow for the values on this leaf.</p>
<ul>
<li><strong>A same-brand runner install keeps them.</strong> The incoming preset's proxy re-binds to the table the
project already holds rather than replacing it, and the sweep that follows keeps every per-case
table the new runner resolves through a proxy.</li>
<li><strong>A switch to any other brand destroys them.</strong> No other preset proxies a frame table, so the sweep
removes it, and switching back installs a fresh all-zero table rather than the one that was there.
The brand switch's optional carry salvages a corner of it: the offsets are read from the outgoing
provider before the swap and written into the incoming one afterwards, but only for ids the
incoming provider already enumerates. No other shipped provider allocates a <code>G5xx</code> id — the
Fanuc-family and Syntec tables enumerate <code>G54</code>–<code>G59</code> and <code>G54.1P1</code>–<code>G54.1P48</code>, the Heidenhain datum
table <code>G54</code>–<code>G59</code> — so the carry keeps <code>G54</code> through <code>G57</code> and the whole extended tail is lost.
What a switch keeps, resets and destroys elsewhere is <a class="xref" href="../machine/brand-switch.html">Brand Switch</a>;
which leaf exists on which brand is <a class="xref" href="../brand-matrix.html">Brand Matrix</a>.</li>
</ul>
<h2 id="what-a-run-writes-back">What a Run Writes Back</h2>
<p>A played program does not only read this table; it writes into it, through a bridge with two
halves.</p>
<ul>
<li><strong><code>$P_UIFR[n,axis,TR]=…</code> writes into it.</strong> A literal numeric assignment is routed into the table:
an X, Y or Z component replaces that component of the frame entry, and any other axis letter lands
in the per-axis dictionary. A non-literal right-hand side is left for the expression evaluator
earlier in the same block, and a write to index <code>0</code> is consumed and ignored, mirroring the cancel
frame's own rule. With no frame table on the runner the bridge is a no-op and the assignment stays
visible as unconsumed residue.</li>
<li><strong><code>$P_UIFR</code> reads come back out of it.</strong> The same mapping serves the read side, answering zero for
an allocated frame's unset axis component and for every component of <code>G500</code>, and null — a
fall-through to the next lookup in the chain — for an id the table does not hold.</li>
</ul>
<p>The table is deliberately <strong>not</strong> session-resettable. Settable frames are setting data on a real
control: a <code>$P_UIFR</code> write survives reset and power-off, so a replayed session must see what the
previous run left. The runner clears every session-resettable dependency on the fresh-session edge
and this table is not among them, which means a value a run wrote is what this panel shows
afterwards, and what the project file keeps.</p>
<p>Which frame a program starts on is not stored in the table either. The Siemens preset's static
initializer seeds the first block's coordinate id as <code>G500</code>, so an untagged Siemens program begins
with no frame active and a zero offset until a frame word appears — unlike the Fanuc-family and
Syntec presets, which begin on <code>G54</code>.</p>
<h2 id="layout">Layout</h2>
<ul>
<li><strong>General Setup</strong> Control Tree — the left dock of <code>/general-setup</code>
<ul>
<li><strong>Controller</strong> Node Row
<ul>
<li><strong>Program Data</strong> Group Row — <code>equipment/controller/program-data</code>
<ul>
<li><strong>Frames (Siemens)</strong> Node Row — <code>equipment/controller/program-data/frames</code>; grown while the
snapshot reports a Siemens frame table</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>Editor Row — the panel of whichever node is selected
<ul>
<li><strong>Frames (Siemens)</strong> Panel
<ul>
<li>No-Runner Body — <em>&quot;No NC runner — load a project first.&quot;</em>; the shared empty state, shown
instead of everything below while the snapshot reports no runner</li>
<li>Absent-Table Body — <em>&quot;No Siemens frame table on the active runner.&quot;</em>; shown instead of
everything below while the panel's own read reports no table</li>
<li>Header Strip
<ul>
<li>Description Caption — <em>&quot;Settable frames ($P_UIFR, translation only); G500 cancels and stores
nothing.&quot;</em>, left-aligned and grey</li>
<li><strong>Show all</strong> Toggle — right-aligned, dense; always rendered</li>
</ul>
</li>
<li>Frame Table — dense, flat, bordered; no sort, no pagination, no column menu
<ul>
<li>Header Row — <strong>Frame</strong>, <strong>X (mm)</strong>, <strong>Y (mm)</strong>, <strong>Z (mm)</strong>. Only <strong>Frame</strong> is translated</li>
<li>Frame Row, one per visible id — not clickable, and carrying no tooltip
<ul>
<li>Frame Id Label — bold plain text, never editable</li>
<li>Value Numeric Field, one per axis column — no minimum, no maximum, no unit suffix</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>Toast — negative, three seconds, the panel's context followed by the server's own message</li>
</ul>
</li>
</ul>
<p>The panel carries no heading, no add or delete control, no reset button, no save button and no
unsaved marker.</p>
<h2 id="source-code-path">Source Code Path</h2>
<p>See <a class="xref" href="../../../index.html">HiNC App Anatomy</a> for git repository links.</p>
<h3 id="web-application">Web Application</h3>
<p>HiNC-2025-webservice (Quasar CLI SPA):</p>
<ul>
<li><code>wwwroot-src/src/components/controlTree/SoftNcFramesPanel.vue</code> — the panel: the two empty layers,
the fixed description and the unconditional <strong>Show all</strong> toggle, the four-column table with its two
literal header spellings, the always-visible regular expression, and the whole-triad cell commit
with its null and non-finite guard.</li>
<li><code>wwwroot-src/src/components/controlTree/SoftNcWorkCoordinatesPanel.vue</code> — the other node on this
table: the same ids and values through the ISO reader, plus the wider always-visible test, the
conditional toggle, the P0 and M0 actions and the canvas marker this leaf has none of.</li>
<li><code>wwwroot-src/src/components/controlTree/softNcItemTypes.ts</code> — the branch builder: this leaf's node
id and label key, the snapshot flag it is pushed behind, and its position among the program-data
children.</li>
<li><code>wwwroot-src/src/components/controlTree/SoftNcEmptyState.vue</code> — the shared no-runner line the panel
opens with.</li>
<li><code>wwwroot-src/src/components/widgets/NumericInput.vue</code> — the value cell: commit on blur or Enter,
the empty-text-to-null parse, and the infinity and NaN literals the panel's handler then rejects.</li>
<li><code>wwwroot-src/src/api/softNcRunner.ts</code> — the frames reader and its whole-triad setter, the shared
offset-row shape and parser both leaves reuse, and the presence flag this leaf is gated on.</li>
<li><code>wwwroot-src/src/api/http.ts</code> — the envelope helper that turns a <code>success: false</code> body into a
thrown error indistinguishable from a transport failure.</li>
<li><code>wwwroot-src/src/composables/useSoftNcRunner.ts</code> — the shared snapshot the first empty layer reads.</li>
<li><code>wwwroot-src/src/i18n/en/softNc.ts</code> — the node label, the description, the <strong>Frame</strong> column header,
the absent-table line and the two error contexts.</li>
<li><code>wwwroot-src/src/i18n/en/common.ts</code> — the shared <strong>Show all</strong> label.</li>
<li><code>Mech/SoftNcRunnerController.cs</code> — the REST surface: the presence probe behind the node's gate, the
unsorted frames reader with its zero fill, the per-id writer that assigns into the dictionary
directly rather than through the coordinate accessor, the work-coordinate routes that share the
same object on this brand, and the brand switch's capture-swap-carry-sweep with its accepted-id
filter.</li>
</ul>
<h3 id="hiapi-engine">HiAPI Engine</h3>
<ul>
<li><code>HiMech/NcParsers/Dependencys/Siemens/SiemensFrameTable.cs</code> — the table: the ninety-nine ids its
constructor seeds, the cancel frame it keeps out of them, the coordinate accessors the
work-coordinate leaf uses, the per-axis accessors the <code>$P_UIFR</code> bridge uses, the axis dictionary
neither panel exposes, the deliberate absence of session-reset, and the id-sorted serialization
that decides the row order after a reload.</li>
<li><code>HiMech/NcParsers/Dependencys/Siemens/SiemensFrameTableProxy.cs</code> — the seedless get-or-create
placeholder: what the runner file records, and the fresh table it installs into a project holding
none.</li>
<li><code>HiMech/NcParsers/Dependencys/IIsoCoordinateConfig.cs</code> — the offset-provider contract this table
implements, which is what makes it the work-coordinate leaf's provider on this brand.</li>
<li><code>HiMech/NcParsers/Dependencys/Siemens/SiemensMachineDataTable.cs</code> — the <code>MD</code> table beside it,
carrying no frames and implementing no offset-provider contract.</li>
<li><code>HiMech/NcParsers/Keywords/Siemens/SiemensKeywords.cs</code> — the cancel frame and the extended series
the constructor seeds from.</li>
<li><code>HiMech/NcParsers/Keywords/Generic/IsoKeywords.cs</code> — the <code>G54</code> series the ISO syntax recognises,
wider than this table allocates.</li>
<li><code>HiMech/NcParsers/SoftNcRunner.cs</code> — the Siemens preset that carries the frame-table proxy as its
first per-case entry, behind only the brand marker; the proxy resolution every read goes through;
and the session-reset sweep this table is deliberately outside of.</li>
<li><code>HiMech/NcParsers/ISessionResettable.cs</code> — the marker the table does not carry, and the difference
between session state and setting data it draws.</li>
<li><code>HiMech/NcParsers/NcRunnerSuit.cs</code> — the per-case list the table hangs off and the proxy wiring
that installs it.</li>
<li><code>HiMech/NcParsers/LogicSyntaxs/CoordinateOffsetUtil.cs</code> — the resolver that walks every provider
and takes the first non-null answer, the coordinate section it writes, and the translation it
composes.</li>
<li><code>HiMech/NcParsers/LogicSyntaxs/Siemens/SiemensCoordinateOffsetSyntax.cs</code> — the frame-word path: the
vocabulary it detects, the flag it leaves in place, the modal lookback, and the zero fallback when
nothing answers.</li>
<li><code>HiMech/NcParsers/LogicSyntaxs/IsoCoordinateOffsetSyntax.cs</code> — the sibling registered beside it on
this preset, writing the same chain entry from the <code>G54</code>–<code>G59.9</code> vocabulary.</li>
<li><code>HiMech/NcParsers/LogicSyntaxs/Siemens/SiemensProgrammableFrameSyntax.cs</code> — the computed
programmable frame, and the entry it shares with the tilt cycle ahead of the settable frame's.</li>
<li><code>HiMech/NcParsers/Syntaxs/SiemensSyntaxUtil.cs</code> — the slot order that decides the composition:
tilt and programmable frame, tool height, the two coordinate syntaxes, then the pivot transform.</li>
<li><code>HiMech/NcParsers/Syntaxs/TransformationUtil.cs</code> — the transform chain: in-order multiplication,
replacement of a repeated entry in place, and the pivot entry that must stay last.</li>
<li><code>HiMech/NcParsers/LogicSyntaxs/MachineCoordSelectSyntax.cs</code> — the one-shot codes that bypass the
composed transform, widened on this preset to <code>G153</code> and <code>SUPA</code>.</li>
<li><code>HiMech/NcParsers/EvaluationSyntaxs/Siemens/SiemensUifrWritingSyntax.cs</code> — the write half of the
<code>$P_UIFR</code> bridge: the literal-only rule, the ignored cancel-frame index, and the no-op when no
frame table resolves.</li>
<li><code>HiMech/NcParsers/EvaluationSyntaxs/Siemens/SiemensUifrVariableLookup.cs</code> — the read half.</li>
<li><code>HiMech/NcParsers/EvaluationSyntaxs/Siemens/SiemensVariableKey.cs</code> — the index-to-id map behind
both halves, and the <code>TR</code>-only key pattern.</li>
<li><code>HiMech/NcParsers/EvaluationSyntaxs/Siemens/SiemensSystemVariableSyntax.cs</code> — where a non-<code>TR</code>
frame component goes instead: recorded on the block, reported unsupported, never reaching the
frame table.</li>
<li><code>HiMech/NcParsers/Initializers/StaticInitializer.cs</code> — the Siemens preset's first-block coordinate
id, and the two brands that differ from it.</li>
<li><code>HiMech/NcParsers/Dependencys/IsoCoordinateAddressMap.cs</code> — the Fanuc-family id set the brand
switch's carry intersects this table against.</li>
<li><code>HiMech/NcParsers/Dependencys/Heidenhain/HeidenhainDatumTable.cs</code> — the third id set the same carry
can meet.</li>
</ul>
<h2 id="see-also">See Also</h2>
<ul>
<li><a class="xref" href="index.html">Program Data Plane</a> — the plane this leaf sits on, and the ownership rules that
decide what a runner install keeps and what a brand switch sweeps</li>
<li><a class="xref" href="work-coordinates.html">Work Coordinates</a> — the other node on this table, where the same ids are
edited as G54 offsets, with the row actions and the canvas marker this leaf has none of</li>
</ul>
</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>