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/util/stl-preview-pane.html
T
2026-09-11 03:46:11 +08:00

434 lines
28 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>STL Preview Pane | HiAPI-C# 2025 </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="STL Preview Pane | 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-StlPreviewPane">
<h1 id="stl-preview-pane">STL Preview Pane</h1>
<p>The STL Preview Pane is the server-rendered 3D view that takes over the File Explorer's editor
column while an <code>.stl</code> file is open. It is neither a route nor a dialog of its own: it renders
inside the right-hand slave panel of <code>/util/file-explorer</code>, and of the modal file picker built on
the same browser component, replacing the text editor's bar and body for as long as an STL is
selected. It carries its own rendering connection, its own copy of the file's triangles, and a
Transform section that can bake a pose back into the file on disk.</p>
<h2 id="where-it-renders">Where It Renders</h2>
<p>The File Explorer mounts the pane on the root-relative path of the STL being previewed; the named
root and that path are both pinned when the preview opens, so switching the explorer's root closes
the preview rather than silently re-targeting it. Three gestures open one, and all key on the <code>stl</code>
extension alone:</p>
<ul>
<li>Selecting the row, but only while the editor slave panel is showing.</li>
<li>Submitting the file's path in the toolbar's path field, under that same panel-showing guard.</li>
<li>Double-clicking the row header, which shows the panel first.</li>
</ul>
<p>Panel visibility starts from the device-local File Explorer preferences on the page and defaults to
shown. Inside the modal picker it always starts hidden and is never written back, so there the
double-click is the only gesture that reaches a preview until the toolbar's editor-panel toggle is
pressed — and in a save-mode picker, where the path field names the save target rather than a place
to navigate to, submitting it never opens a preview at all.</p>
<p>Four gestures close one: the bar's own close button, opening a text file in the same panel, a root
switch, and the toolbar's editor-panel toggle. The first three leave the panel showing the text
editor; the last settles the text buffer, hides the whole panel and drops the preview together.</p>
<h2 id="layout">Layout</h2>
<ul>
<li>STL Preview Pane
<ul>
<li>Preview Bar
<ul>
<li>Location Label — the root's display name and the root-relative path, ellipsized, with the
full string as its hover title.</li>
<li>Triangle Count Badge — an outlined badge rendered only once a load has reported a count, and
cleared again at the start of every new load. The number is formatted for the app locale.</li>
<li><code>Scene ▾</code> Menu — the shared display-options dropdown, carrying one checkbox here,
<strong>Origin axes</strong>.</li>
<li><code>View ▾</code> Menu — the shared
<a class="xref" href="../widget/renderingcanvas-tool-bar.html">RenderingCanvas Tool Bar</a>, bound to this pane's canvas.</li>
<li><strong>Transform</strong> Button — shows and hides the Transform section; it reads primary-coloured while
the section is open, and starts off on every mount.</li>
<li>Close Button — a round <code>close</code> icon titled <strong>Close preview</strong>.</li>
</ul>
</li>
<li>Transform Section — rendered only while the Transform button is on.
<ul>
<li>Header Row — a <strong>Transform</strong> caption and a <strong>Save</strong> button. Save stays disabled until a load
has published a transform key, and shows a loading state while the write is in flight.</li>
<li>General Transform Editor — the standard transformer editor, scrolling inside a capped height
so the canvas keeps most of the pane:
<ul>
<li><strong>Scale</strong> numeric field.</li>
<li><strong>Rotation sub-transformer</strong> card — <strong>Rotation axis</strong> as three components with a normalize
button, <strong>Angle</strong> in degrees, and <strong>Pivot</strong> in mm.</li>
<li><strong>Translation sub-transformer</strong> card — a <strong>Translation</strong> caption over three mm components.</li>
<li>A caption naming the composed transform as <code>T × R × scale × I</code>.</li>
<li>Every field here commits on blur or on Enter, one write per field.</li>
</ul>
</li>
<li>Failure Text — with no transform key held, the section reads &ldquo;Failed to load STL preview.&rdquo; in
place of the editor.</li>
</ul>
</li>
<li>Canvas Body
<ul>
<li>Rendering Canvas — fills the rest of the pane.</li>
<li>Loading Overlay — a centred spinner over a dim, click-through wash. The previously loaded
model stays visible beneath it rather than being cleared.</li>
<li>Error Banner — pinned to the foot of the canvas, carrying the failed load's message.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="loading-a-preview">Loading a Preview</h2>
<p>One request path serves every trigger: the canvas reporting a connection id, and any change to the
root or the relative path. Each request clears the banner and the triangle badge, raises the
spinner, and posts the named root and the relative path to <code>show</code>.</p>
<p>Server side, the controller resolves the root name, re-combines it with the relative path, refuses
a result that is not a descendant of that root, and refuses a path that does not exist. The read
itself runs on a thread-pool task rather than the request thread, and the format is sniffed from
the file's first two lines rather than from its extension — ASCII and binary STL both load. The
file is opened for shared read and write, so a load does not lock it against other readers.</p>
<p>A successful read builds the native topology, commits it into the connection's slot, and only then
touches the engine: the displayee is re-pointed at the new composition, the camera is reset to the
engine's home view and the render cache cleared, and the geometry the commit replaced is disposed
afterwards, so the render thread never spends a frame on a dead reference.</p>
<p>The response carries the triangle count, the bounding box, the connection's origin-axes flag and
the transform key. The pane reads all of those except the bounding box, which it ignores — the
bounding-box readout a reader sees belongs to the StlFile Editor's info dialog, not to this pane.</p>
<p>A rejected load — unknown or unavailable root, a path escaping the root, a missing file, an
unreadable file — answers a non-2xx status carrying the server's message, and the shared response
helper folds the status into the text; that composite is what the banner shows. The message itself
is passed through as the server wrote it: unlike the File Explorer's own endpoints, this controller
runs no root-prefix scrub over an exception message, so a read or write that fails down in the
filesystem layer can surface a server path in the banner.</p>
<h2 id="cancelling-a-load">Cancelling a Load</h2>
<p>Cancellation is the pane's defining behaviour: clicking down a folder of large STLs does not stack
multi-second reads behind each other, and the tree stays fully interactive throughout.</p>
<p>Three mechanisms compose:</p>
<ul>
<li><strong>A monotonic show token in the pane.</strong> Every request takes the next number; a response arriving
under a stale number is discarded, and the spinner is lowered only by the newest request. Without
it the slower of two racing round-trips would win the badge.</li>
<li><strong>An abort controller in the pane.</strong> Each request aborts the previous one's controller before
issuing its own, and swallows the resulting abort error. The same controller is aborted when the
pane unmounts.</li>
<li><strong>Supersede in the preview service.</strong> Before reading anything the controller asks the service to
supersede the connection, which cancels whatever load is still running and installs a fresh
cancellation source. That source doubles as the commit ticket. The request then reads under a
token linked from the ticket and from the request-aborted token, so a browser abort and a newer
selection cancel the same read.</li>
</ul>
<p>The read is cooperatively cancellable rather than interruptible: the STL reader checks the token
once every 4096 triangles, and once every 4096 lines of the pre-scan an ASCII file needs, which
bounds the latency to a few thousand parses rather than a whole file.</p>
<p>The commit is gated on the ticket. A load that finishes after a newer one superseded it is refused,
disposes the geometry it has just built, and answers HTTP 200 with a <code>canceled</code> flag; the pane drops
that response without touching the badge or the banner, and lowers the spinner only when no newer
request has taken the pane over in the meantime.</p>
<h2 id="the-rendering-connection">The Rendering Connection</h2>
<p>The pane embeds one rendering canvas, so it opens its own SignalR connection to <code>/renderingHub</code> and
the server gives that connection its own display engine — a second live engine beside the host
page's canvas whenever the preview is running inside the modal picker. See
<a class="xref" href="../conventions/rendering-canvas-web-service.html">Rendering Canvas on Web Service Application</a> for the
transport itself.</p>
<p>The connection id is the key for everything on the server side: the display engine, and the preview
service's per-connection slot. The canvas re-emits it after every automatic reconnect, and the pane
answers by re-issuing the show — which is what restores the preview after a connection drop. The
reconnected slot starts empty, so the pane re-pushes its own <strong>Origin axes</strong> preference whenever the
server's answer disagrees with it. The pose is not restored: every commit mints a fresh identity
transform.</p>
<p>Release runs off the connection's death rather than off an explicit teardown call. Closing the
preview unmounts the pane, which aborts the in-flight fetch and disconnects the canvas; the hub's
disconnect handler disposes the engine and raises its engine-removed event; the preview service's
subscriber then cancels any load still running, disposes the STL topology and the origin-axes
drawing, and withdraws the transform key. That subscriber exists because a display engine disposes
only itself — never the displayee it was pointed at.</p>
<p>The <code>clear</code> endpoint performs most of that detach on demand — it cancels the load in flight, empties
the canvas, disposes the topology and withdraws the transform key — but it keeps the connection's
slot registered, with its origin-axes drawing and flag intact for the next preview; only the
connection's death frees those. It is also the one entry in this surface that ships without a caller
in the SPA.</p>
<h2 id="server-side-composition">Server-Side Composition</h2>
<p>The slot a connection owns holds a small display graph rather than a bare mesh:</p>
<ul>
<li><a class="xref" href="../../api/Hi.Geom.Topo.NativeTopoStl3d.html">NativeTopoStl3d</a> — the native topology built from the file's triangles, and one
of the two objects here that have to be disposed by hand.</li>
<li><a class="xref" href="../../api/Hi.Disp.Treat.TransformationWrapper.html">TransformationWrapper</a> — wraps that topology and carries the pose matrix.</li>
<li><a class="xref" href="../../api/Hi.Disp.Flag.CoordinateDrawing.html">CoordinateDrawing</a> — the origin axes, created on first enable and kept across
file switches, because the flag is a per-connection viewing preference rather than a property of
the file. It is the other hand-disposed object, and only the connection's death frees it.</li>
<li><a class="xref" href="../../api/Hi.Disp.DispList.html">DispList</a> — the composition assigned to <a class="xref" href="../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_Displayee">Displayee</a>: the
axes drawing, when shown, followed by the wrapper.</li>
<li><a class="xref" href="../../api/Hi.Mech.Topo.GeneralTransform.html">GeneralTransform</a> — the pose the Transform section drives.</li>
</ul>
<p><a class="xref" href="../../api/Hi.Geom.Stl.html">Stl</a> is not among them. The reader's output is a local of the show request, alive only
long enough for the native topology to copy its triangles into its own buffer and for the response
to report the triangle count and the bounding box; the save path then mints a second one out of the
topology's own snapshot, and it is that second object the save transforms and writes.</p>
<p>The committed topology always holds the file's as-loaded triangles. The editor's pose lives only in
the wrapper, which is why it can be re-applied, reset or saved repeatedly without drift.</p>
<h2 id="transform-and-save">Transform and Save</h2>
<p>Each committed load registers a fresh <a class="xref" href="../../api/Hi.Mech.Topo.GeneralTransform.html">GeneralTransform</a> — identity, and a new
object rather than a reset one — in the server's keyed object store, and returns its key. The pane
hands that key to the standard general-transform editor, the same component and the same REST
surface the Transformer panels use; there is no preview-specific transform schema. After every
committed edit the pane posts <code>apply-transform</code>, which re-reads the transform's matrix into the
display wrapper and clears the render cache. That is display only — the file is untouched.</p>
<p>Save asks for confirmation naming the root-relative path, then bakes. The service snapshots the
native triangles under the topology's own dispose lock, multiplies them by the current matrix and
writes the result over the previewed file as a <strong>binary</strong> STL, so an ASCII source is rewritten in
binary form. Because the shown topology keeps the as-loaded triangles and the editor keeps its
values, screen and disk agree afterwards — both are the original geometry times the current matrix —
and saving twice with the same values rewrites the same file rather than compounding the pose.
Resetting the editor's fields returns to the as-loaded pose.</p>
<p>A save that finds the topology already disposed by a newer selection reports that it was superseded
instead of writing. On success the pane raises a toast and the File Explorer re-lists the containing
folder, so the row's size and modified columns catch up. Nothing else is refreshed: a
<a class="xref" href="../../api/Hi.Geom.StlFile.html">StlFile</a> geometry elsewhere in the project that references the same path keeps the
triangles it already loaded.</p>
<p>Switching files re-mints the transform — a new key, an identity pose, and an editor that re-reads
cleanly because the key changed. The old key is withdrawn from the keyed store on replacement, on
clear and on connection death; the two derived keys the editor mints beneath it for the rotation and
translation sub-transformers are not withdrawn with it.</p>
<h2 id="endpoints">Endpoints</h2>
<p>Every entry is a POST under <code>/api/stl-preview</code>, addressed by the rendering connection id. The four
that touch the canvas resolve the display engine through the non-creating lookup, so a disconnected
id cannot orphan a fresh engine; <code>save</code> needs no engine at all and writes straight from the slot.</p>
<table>
<thead>
<tr>
<th>Path</th>
<th>Body</th>
<th>Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>show/{renderingConnectionId}</code></td>
<td><code>{ rootName, relFile }</code></td>
<td>Supersede, read, commit, re-point the engine. Answers the triangle count, the bounding box, the origin-axes flag and the transform key — or a <code>canceled</code> flag.</td>
</tr>
<tr>
<td><code>set-coordinate/{renderingConnectionId}</code></td>
<td>a bare boolean</td>
<td>Show or hide the origin axes. With nothing on the canvas yet it stores the flag for the next commit.</td>
</tr>
<tr>
<td><code>apply-transform/{renderingConnectionId}</code></td>
<td>none</td>
<td>Re-read the transform's matrix into the display wrapper.</td>
</tr>
<tr>
<td><code>save/{renderingConnectionId}</code></td>
<td>none</td>
<td>Bake the matrix into the geometry and overwrite the file.</td>
</tr>
<tr>
<td><code>clear/{renderingConnectionId}</code></td>
<td>none</td>
<td>Cancel the load in flight, empty the canvas, free the STL geometry; the slot and its origin-axes drawing survive.</td>
</tr>
</tbody>
</table>
<p><code>rootName</code> is one of the three named roots — the admin directory, the loaded project directory and
the shared resource directory — resolved server-side; the project root is unavailable until a
project is loaded. Addressing is root-relative in both directions and the absolute path is formed
and kept on the server; the unscrubbed error text noted above is the one place it can escape.</p>
<h2 id="the-text-buffer-underneath">The Text Buffer Underneath</h2>
<p>Opening a preview does not disturb the text editor beneath it. There is no flush, no discard prompt
and no reload: the loaded path, the buffer, its saved snapshot and its dirty mark are all left as
they were, and the bar's close button brings them straight back, dirty star included. Clicking a
text file while a preview is open closes the preview first and then loads that file through the
editor's normal open path, which settles the outgoing buffer the way any file switch does.</p>
<p>Two consequences follow from the buffer staying live. The toolbar's editor-panel toggle remains
reachable while the preview is up, and it settles the buffer before hiding the panel — so a dirty
buffer in manual mode raises its discard confirm at that point, even though the visible pane is a 3D
canvas. And an auto-save debounce armed just before the preview opened still fires underneath it.</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/StlPreviewPane.vue</code> — this pane: the bar, the Transform section, the
canvas body with its overlay and banner, the show token and abort controller, and the optimistic
origin-axes toggle.</li>
<li><code>wwwroot-src/src/components/FileExplorer.vue</code> — the sole host: the preview slot in the editor
slave panel, the extension test and the three opening gestures, the pinned root, the close paths,
and the folder refresh after a save.</li>
<li><code>wwwroot-src/src/components/widgets/FileExplorerDialog.vue</code> — the modal wrapper, whose picker
props are what leave the editor panel hidden inside the picker.</li>
<li><code>wwwroot-src/src/pages/FileExplorerPage.vue</code> — the routed host at <code>/util/file-explorer</code>.</li>
<li><code>wwwroot-src/src/api/stlPreview.ts</code> — the typed wrapper over the five endpoints, the result shape,
and the abort signal threaded into <code>show</code>.</li>
<li><code>wwwroot-src/src/api/http.ts</code> — the shared response helper that wrapper uses: a non-2xx throws an
error whose text is the status followed by the server's message, while a 200 body carrying
<code>success: false</code> reaches the caller as data, which is what lets the <code>canceled</code> answer be ignored
silently.</li>
<li><code>wwwroot-src/src/components/RenderingCanvas.vue</code> — the connection the pane owns, its reconnect
loop and the re-emitted connection id.</li>
<li><code>wwwroot-src/src/components/RenderingCanvasToolBar.vue</code> — the <code>View ▾</code> menu in the bar.</li>
<li><code>wwwroot-src/src/components/widgets/DisplayOptionsMenu.vue</code> — the <code>Scene ▾</code> dropdown; the pane
passes one checkbox group and no label, so the button falls back to the localized &ldquo;Scene&rdquo;.</li>
<li><code>wwwroot-src/src/components/topo/GeneralTransformEditor.vue</code>,
<code>wwwroot-src/src/components/topo/StaticRotationEditor.vue</code> and
<code>wwwroot-src/src/components/topo/StaticTranslationEditor.vue</code> — the Transform section's editor and
its two sub-transformer cards.</li>
<li><code>wwwroot-src/src/components/widgets/NumericInput.vue</code> and
<code>wwwroot-src/src/components/widgets/Vec3Input.vue</code> — the fields inside them, committing on blur or
Enter.</li>
<li><code>wwwroot-src/src/api/transformer.ts</code>, <code>wwwroot-src/src/api/geometry.ts</code> and
<code>wwwroot-src/src/api/index-service.ts</code> — the standard transform surface those editors write
through.</li>
<li><code>wwwroot-src/src/i18n/en/explorer.ts</code> — the <code>explorer.preview.*</code> strings: the close title, the
failure text, <strong>Origin axes</strong>, <strong>Transform</strong>, and the save-confirm dialog.</li>
<li><code>wwwroot-src/src/i18n/en/geom.ts</code> — the pluralized triangle-count phrase in the badge.</li>
<li><code>wwwroot-src/src/i18n/en/topo.ts</code> and <code>wwwroot-src/src/i18n/en/widgets.ts</code> — the transform-editor
captions, and the <code>Scene</code> and <code>View</code> menu labels.</li>
<li><code>Disp/StlPreviewController.cs</code> — the five endpoints, the root resolution and descendant check, the
off-thread read, the commit-then-swap ordering, the <code>canceled</code> answer, and the failure replies
that pass an exception message through unaltered.</li>
<li><code>Common/FileExplorerController.cs</code> — the root-prefix scrub over exception text that the File
Explorer's own endpoints apply and this surface does not share.</li>
<li><code>Disp/StlPreviewService.cs</code> — the per-connection slot: supersede and the commit ticket, the display
composition, the origin-axes flag that survives file switches, the bake-and-write save, and the
engine-removed handler that frees everything.</li>
<li><code>Disp/RenderingService.cs</code> — the per-connection engine store, the non-creating lookup HTTP
endpoints must use, and the engine-removed event.</li>
<li><code>Disp/RenderingHub.cs</code> — the hub whose disconnect disposes the engine and raises that event.</li>
<li><code>Common/NamedRootResolver.cs</code> — the three named roots and their availability rules.</li>
<li><code>Common/IndexService.cs</code> — the keyed object store the transform is published in.</li>
<li><code>Mech/Topo/GeneralTransformController.cs</code> — the standard transform endpoints, including the two
that index the rotation and translation sub-transformers under derived keys.</li>
</ul>
<h3 id="hiapi-engine">HiAPI Engine</h3>
<ul>
<li><code>HiGeom/Geom/Stl.cs</code> — the reader: content-sniffed ASCII / binary detection, the cancellation check
every 4096 triangles or pre-scan lines, and the binary writer the save uses.</li>
<li><code>HiDisp/Geom/Topo/NativeTopoStl3d.cs</code> — the native topology, and the locked triangle snapshot the
save takes, which answers nothing once the topology has been disposed.</li>
<li><code>HiDisp/Disp/Treat/TransformationWrapper.cs</code> — the display-time pose applied to that topology.</li>
<li><code>HiDisp/Disp/Flag/CoordinateDrawing.cs</code> — the origin-axes drawing.</li>
<li><code>HiDisp/Disp/DispList.cs</code> — the one- or two-element composition the engine is pointed at.</li>
<li><code>HiDisp/Disp/DispEngine.cs</code> — the engine: its displayee, its cache clear, its home view, and a
dispose that frees the native engine alone.</li>
<li><code>HiMech/Mech/Topo/GeneralTransform.cs</code> — the pose model, its uniform scale and its two
sub-transformers.</li>
</ul>
<h2 id="see-also">See Also</h2>
<ul>
<li><a href="file-explorer.html">File Explorer</a> — the one screen that mounts this pane, and the editor column it
takes over</li>
<li><a class="xref" href="../geom/stlfile-editor.html">StlFile Editor</a> — the geometry editor whose file picker is where this preview is
most often met, and the surface that owns the bounding-box readout this pane does not show</li>
<li><a class="xref" href="../widget/renderingcanvas-tool-bar.html">RenderingCanvas Tool Bar</a> — the <code>View ▾</code> and <code>Scene ▾</code> menus the preview bar embeds</li>
<li><a class="xref" href="../conventions/rendering-canvas-web-service.html">Rendering Canvas on Web Service Application</a> — the hub connection the pane opens, and the
engine-removed event that frees the preview's native geometry</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>