This commit is contained in:
2026-09-11 03:46:11 +08:00
parent 45b9f9ed5d
commit b7f55aa631
114 changed files with 3646 additions and 576 deletions
@@ -0,0 +1,244 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Geometry Editor | HiAPI-C# 2025 </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Geometry Editor | 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-GeomManageControl">
<h1 id="geometry-editor">Geometry Editor</h1>
<p>The geometry switchboard is one control: a kind picker over the kinds its host allows, and — unless
the host asked for the picker alone — the picked kind's editor beneath it. It binds a
<strong>key into the shared object store</strong>, not an object, and every Control-Tree Geometry slot is this
same control in selector-only mode.</p>
<h2 id="layout">Layout</h2>
<p>Web: a geometry-type dropdown; a separator, drawn only while a kind is active; then that kind's
editor. Picking a kind commits immediately — there is no Apply button. In selector-only mode
everything below the dropdown is dropped, which is the form each Geometry slot node shows.</p>
<h2 id="what-it-binds">What It Binds</h2>
<p>The web panel has no target-geometry property. It takes a <code>modelKey</code> naming the object it edits and
mutates what sits behind that key; a host that also owns the <em>field</em> holding the geometry passes an
<code>onCreate</code> hook, so switching the kind rebinds the host's field rather than just the key.</p>
<p>Each host's field type decides which kinds it <em>may</em> offer; whether the kind survives a save decides
which of those it <em>does</em>. A fixture's geometry and a transformation geometry's inner geometry are
<a class="xref" href="../../api/Hi.Geom.IGetStl.html">IGetStl</a>; a workpiece's initial geometry is an <code>IMakeXmlSource</code>, which is why the
cube-tree file — which is not an <code>IGetStl</code> — reaches that picker and no other.</p>
<p>Type compatibility alone is not sufficient, and <a class="xref" href="../../api/Hi.Geom.ExtendedCylinder.html">ExtendedCylinder</a> is the case that
shows it. It is an <code>IMakeXmlSource</code>, so the workpiece's raw slot could hold one and once did — but
its start section is supplied by a host at run time and is not serialized, so a saved project
reloaded it with a zero-radius start and the shape degenerated. The kind is now offered by the one
host that wires that source, the cutter's upper beam.</p>
<h2 id="reach">Reach</h2>
<p>The picker's own default is <strong>six of the seven kinds</strong>: <a class="xref" href="../../api/Hi.Geom.Box3d.html">Box3d</a>,
<a class="xref" href="../../api/Hi.Geom.Cylindroid.html">Cylindroid</a>, <a class="xref" href="../../api/Hi.Geom.StlFile.html">StlFile</a>, <a class="xref" href="../../api/Hi.Geom.TransformationGeom.html">TransformationGeom</a>,
<a class="xref" href="../../api/Hi.Geom.GeomCombination.html">GeomCombination</a> and <a class="xref" href="../../api/Hi.Cbtr.CubeTreeFile.html">CubeTreeFile</a>. <a class="xref" href="../../api/Hi.Geom.ExtendedCylinder.html">ExtendedCylinder</a> is
in the kind map but out of that default: a host that can wire its start section names it explicitly.
Nothing is hidden by a flag.</p>
<p><strong>The default is a guard rail, not a shipped list.</strong> Every host passes its own whitelist — the five
Control-Tree Geometry slots from the node context, the four inline hosts as a constant — so no
shipped surface renders the default at all, and the whitelist is what really decides reach.</p>
<table>
<thead>
<tr>
<th>Host</th>
<th>Kinds offered</th>
</tr>
</thead>
<tbody>
<tr>
<td>Fixture geometry, mechanism anchor, a transformation geometry's inner geometry, a combination child</td>
<td>the five container kinds — Box3d, Cylindroid, StlFile, TransformationGeom, GeomCombination</td>
</tr>
<tr>
<td>Workpiece raw geometry</td>
<td>six — the five container kinds plus CubeTreeFile</td>
</tr>
<tr>
<td>Workpiece target geometry</td>
<td>four</td>
</tr>
<tr>
<td>Cutter upper beam</td>
<td>six — Cylindroid, ExtendedCylinder, TransformationGeom, StlFile, Box3d, GeomCombination</td>
</tr>
</tbody>
</table>
<p>A null geometry is a legal state of the model, but the web picker offers its <strong>None (unset)</strong> entry
only when the host asks for it: the three General Setup slots and a transformation geometry's inner
geometry do, while the mechanism anchor, the cutter upper beam and combination children do not, so
those pickers cannot clear the slot. Clearing goes through the host's create hook with the literal
kind <code>None</code>, which the container-aware endpoints map to null.</p>
<h2 id="there-is-no-way-to-wrap-an-existing-geometry">There Is No Way to Wrap an Existing Geometry</h2>
<p>Wrapping a geometry that is already in a slot into a <a class="xref" href="../../api/Hi.Geom.TransformationGeom.html">TransformationGeom</a> — and
extracting it back out — is not offered anywhere in the application, and the difference from what
the picker looks like it does is not cosmetic. <strong>Picking <code>TransformationGeom</code> creates a new, empty
one and discards the geometry that was there.</strong> The same holds for a combination: there is no
operation that takes a geometry and puts a container around it in place.</p>
<h2 id="in-the-control-tree">In the Control Tree</h2>
<p><code>Geometry</code> is a slot item type. Its child builder probes the slot's key for the type behind it and,
when that type is a known kind, grows exactly <strong>one</strong> child node of that kind bound to the same key
— so the slot node carries the picker and its single child carries the editor. Five kinds resolve to
the shared sole-editor panel; <code>TransformationGeom</code> and <code>GeomCombination</code> instead map to panels of
their own, because they grow further slot children rather than hosting one editor. The two
file-backed kinds compose the referenced file into their node label.</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>
<p>HiNC-2025-webservice (Quasar CLI SPA):</p>
<ul>
<li><code>wwwroot-src/src/components/geom/GeometryEditor.vue</code> — the switchboard: the kind picker over the
allowed kinds, the opt-in unset entry, the immediate commit through the create hook, and the
active kind's editor.</li>
<li><code>wwwroot-src/src/components/geom/geometryEditors.ts</code> — the single kind → editor map both this
picker and the Control Tree's sole-editor panel resolve through.</li>
<li><code>wwwroot-src/src/components/controlTree/GeometrySlotPanel.vue</code> — the slot node's panel: this
switchboard in selector-only mode, fed its allowed kinds, its unset flag and its create hook from
the node.</li>
<li><code>wwwroot-src/src/components/controlTree/SoleEditorPanel.vue</code> — the kind child's panel.</li>
<li><code>wwwroot-src/src/components/controlTree/itemTypes.ts</code> — registers <code>Geometry</code> as a slot type with
its child builder, registers each kind against its panel, and holds both the container-kind list
and the file-backed node labels.</li>
<li><code>wwwroot-src/src/components/controlTree/useControlTreeHost.ts</code> — the three General Setup Geometry
slots and their per-host kind whitelists.</li>
<li><code>wwwroot-src/src/pages/MechBuilderPage.vue</code> and
<code>wwwroot-src/src/components/toolhouse/UpperBeamDiv.vue</code> — the two inline, non-tree hosts.</li>
<li><code>wwwroot-src/src/api/index-service.ts</code> — the type probe the picker calls to discover which kind is
currently behind the key.</li>
<li><code>wwwroot-src/src/api/geometry.ts</code> — the kind union, the create dispatcher and its per-kind
endpoint map, and every per-kind call.</li>
<li><code>wwwroot-src/src/api/fixture.ts</code>, <code>wwwroot-src/src/api/workpiece.ts</code>,
<code>wwwroot-src/src/api/toolHouse.ts</code> and <code>wwwroot-src/src/api/generalMechanism.ts</code> — the
container-aware create wrappers each host's hook posts through.</li>
<li><code>wwwroot-src/src/i18n/en/common.ts</code> and <code>wwwroot-src/src/i18n/en/geom.ts</code> — the picker's label and
its unset and empty-state strings. Geometry type names are deliberately not translated.</li>
<li>The seven per-kind controllers under <code>Geom/</code> — <code>Geom/Box3dController.cs</code>,
<code>Geom/CylindroidController.cs</code>, <code>Geom/ExtendedCylinderController.cs</code>, <code>Geom/StlFileController.cs</code>,
<code>Geom/CubeTreeFileController.cs</code>, <code>Geom/TransformationGeomController.cs</code> and
<code>Geom/GeomCombinationController.cs</code> — each at <code>/api/{Kind}/*</code>. There is no single geometry
controller and no geometry hub.</li>
<li><code>Common/IndexController.cs</code> — the type probe at <code>/api/Index/GetType</code>.</li>
<li><code>Common/IndexService.cs</code> — the keyed object store all of the above read and write. There is no
per-panel session object.</li>
<li><code>Mech/FixtureController.cs</code>, <code>Mech/WorkpieceController.cs</code>, <code>Mech/CutterController.cs</code> and
<code>Mech/MechBuilder/GeneralMechanismController.cs</code> — the container-aware create endpoints that set
the host's own field, and the ones that accept <code>None</code> and store null.</li>
</ul>
<h2 id="see-also">See Also</h2>
<ul>
<li><a class="xref" href="../util/mech-builder.html">Mechanism Builder Page</a> — embeds this control under its anchor
editor</li>
<li><a href="box3d-editor.html">Box3d Editor</a> — the kind editors this switchboard resolves</li>
<li><a href="cylindroid-editor.html">Cylindroid Editor</a> — the same, for a solid of revolution</li>
<li><a href="extended-cylinder-editor.html">ExtendedCylinder Editor</a> — the same, and the kind exactly one host offers</li>
<li><a href="stlfile-editor.html">StlFile Editor</a> — the same, for an STL reference</li>
<li><a href="meshed-geom-file-editor.html">MeshedGeomFile Editor</a> — the same, for a voxel cube tree</li>
<li><a href="transformation-geom-editor.html">TransformationGeom Editor</a> — one of the container kinds
this panel offers, and why picking it replaces rather than wraps</li>
<li><a href="geom-combination-editor.html">GeomCombination Editor</a> — the other container kind, whose
every child embeds this panel again</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>