Table of Contents

Equipment Topology Column

The Topology column is the Equipment page's fourth column: the whole authored equipment — machine tool, fixture, workpiece and tool — drawn as one anchor / branch graph, with an editor card below it for whichever anchor, branch or assembly is picked. It is where a part's anchors, branches, transformers and solids are authored; the Control Tree's three mechanism items only bind roles — which of a part's own anchors and branches play its Table Mount, its Geometry Anchor, its Axis X — and a role armed there is bound by clicking its element in this graph. It has one surface:

  • the rightmost column of the Equipment page (/equipment), titled Topology. It carries no ?tree= id of its own: the graph is not a Control-Tree branch, and a part's cluster in it is a shortcut to that part's tree item.

The column order is TREE | EDITOR | CANVAS | TOPOLOGY, one column-toggle button each in the menu bar's column-button row — the fourth button, titled “Toggle the Topology column”. Its first-run visibility follows the window — shown on one at least 1280 px wide, hidden on a narrower one — and is stored with the rest of the device-local view preferences at their next write; a stored bit wins whatever the window is afterwards. Its width is device-local (the topologyColPx view preference, default 420 px) and it is pinned to 0 px rather than unmounted while hidden, so the graph keeps its selection and scroll. When the canvas is hidden and the Topology column shown, the column takes the canvas's width.

Layout

Title Bar

  • Refresh — an icon button (tooltip Refresh) at the right end of the column's title bar, spinning while a pull is in flight and disabled while an edit is; re-pulls the graph and every part's roles.

Armed-Role Strip

A strip between the title bar and the graph, shown only while a role is armed on a Roles panel: a chip reading "Pick {element} in the {owner} to bind {role}.", removable to disarm.

Graph

The graph is drawn by the graph view MechBuilderGraph.vue, whose name is historical. Every assembly with an anchor somewhere below it is a cluster titled with the assembly's name, nested as the assemblies nest: the equipment's own assembly (SetupEquipment) outermost and untagged, one cluster per part inside it — the part's key assembly, its title tagged Machine Tool, Fixture, Workpiece or Tool — and a part's sub-assemblies inside that. Above the graph sits the graph view's own toolbar — the flow direction (top-down or left-to-right), zoom out, the scale (a click returns to actual size), zoom in and fit to width — and the graph scrolls in its own region, which a drag pans once the graph overflows it. A height divider under the graph sets its height (the device-local topologyGraphPx view preference, default 320 px); the editor card below it takes the rest.

  • The tool is not edited here: its cluster holds only its assembly clusters and the anchor its attachment reaches, never its own anchors and branches.
  • An anchor bound to a role carries a badge under its label naming the part and the role in the UI language — Fixture · Table Mount, Machine Tool · Tool Mount — and an outlined node style; a branch bound to an axis role carries its badge too (Machine Tool · Axis X). The badges are gathered from every part, not only from the part the element belongs to, so an element more than one part points at shows one badge per part.
  • A part's own branch is a solid edge and an attachment between parts a dotted one. An edge is labelled name (transformer type), the transformer type alone when the branch has no name, and Attachment when it has neither.
  • Clicking an anchor selects it and opens the anchor editor; clicking a branch selects it and opens the branch editor; clicking a cluster selects that assembly and — when it belongs to the machine tool, fixture or workpiece — moves the Control Tree to that part's mechanism item, so its Roles panel sits beside the graph. The three selections are mutually exclusive.
  • With no project open the graph area reads “Open a project to see its equipment topology.”

Editor Card — Anchor

Header: the title Anchor, a Root badge on the part's root anchor, an owner chip (Machine Tool / Fixture / Workpiece / Tool / Equipment); below it, one badge per role bound to the anchor — the same text the graph draws, with the language-neutral form the REST graph carries (Fixture-TableMount) as its tooltip.

  • On an editable owner (a machine tool that is a GeneralXyzabcMachineTool, the fixture, the workpiece):
    • Name — renamed on Enter or when the field is left, never while typing.
    • Extend — a new anchor linked from this one by a NoTransform branch; the new anchor becomes the selection.
    • Delete — the trash button, on a double-click; not offered on the root anchor. A role bound to the anchor, or an axis role bound to a branch the deletion takes with it, is unbound first and named in a toast ("Unbound roles: …").
    • Add Branch — a select over the part's other anchors not already joined to this one in either direction; picking one creates a NoTransform branch from this anchor to it.
    • Geometry — a checkbox that hangs a solid on the anchor or removes it, and while enabled a type badge (the kind, or Transformed {kind}), the display-colour swatch (an authored colour beside a reset button, or the automatic one marked auto) and the Geometry Editor over the solid's geometry. The editor's kind picker offers Box3d, Cylindroid, StlFile and GeomCombination, and no None entry; beneath it the Transform picker puts a transform on the picked geometry in place, and the transformer's editor follows the geometry's. A freshly enabled solid holds an empty wrapper, which the card reads as no kind picked yet. The section is not offered on the workpiece at all, whose anchors carry no solids. On the fixture's Geometry Anchor the checkbox cannot be cleared (the server refuses disable-geom and the box snaps back with a toast), and with no None in the picker that solid's geometry can be switched to another kind here but emptied only over HTTP (create-geom?geometryType=None).
  • On a non-editable owner (the tool, or a ClMillingDevice machine) the card shows only “{type} is shown here but not editable.”

Editor Card — Branch

Header: the title Branch, the owner chip, an Attachment chip on a branch between parts, and the badge of an axis role bound to the branch, on its own row below.

  • Name (editable on a part's own branch only; disabled on an attachment, which is named by its role pair), the two endpoint chips (fletch → arrow anchor), the current transformer type, and the transformer editor: the shared Transformer Select Panel switchboard, which swaps the branch's transformer as soon as a kind is picked and re-posts an inner-value edit so the canvas follows.
  • The worktable attachment — the machine's table end into the fixture's Table Mount, or into the workpiece's Fixture Mount when the project has no fixture — is the one attachment with an editable transformer: the equipment's TableToComp, edited under owner equipment. Every other attachment shows “Only the worktable attachment carries an editable transformer; the other attachments follow their roles.”
  • Delete (double-click) on a part's own branch; an axis bound to it is unbound first and toasted.
  • A branch of a non-editable part (a ClMillingDevice machine) shows only “{type} is shown here but not editable.”

Editor Card — Assembly

Clicking a cluster shows the card headed Mechanism, with the owner chip of the part the assembly belongs to.

  • On an editable part (the machine tool, fixture or workpiece): a Name field that renames the assembly — on Enter or when the field is left; the server refuses a name carrying the path separator, one that opens like a GUID segment, and one a sibling assembly already carries — then the part's runtime type, “Roles are bound on this part's item in the Control Tree.” and an Open roles button that selects that item.
  • On any other assembly (the tool's, the equipment's own, a ClMillingDevice machine's): the assembly's name as plain text, the type line and “{type} is shown here but not editable.”

Roles Panel (on the Control Tree)

Each of the three mechanism root panels — Machine Tool, Fixture, Workpiece — ends with the Roles panel, titled Roles: one row per role, with the role's label, a caption naming its kind (anchor or branch), “required” where the part needs it, and “needs {transformer type}” on an axis role; a clearable select over the part's own anchors or branches (a role bound outside the part is listed by name at the top so the select can show it); and the arm button, a target icon whose tooltip reads “Pick on the graph” (lit while its role is armed). Below the list, the server's checks — or “All checks pass.” A part the project has not mounted shows “Not mounted.” instead of the rows, and a part whose type has no editable roles (a ClMillingDevice machine) “{type} has no editable roles.”

Part Roles Kind Note
Machine tool Table Mount, Tool Mount anchor required
Machine tool Axis X, Axis Y, Axis Z branch optional; needs DynamicTranslation
Machine tool Axis A, Axis B, Axis C branch optional; needs DynamicRotation
Fixture Table Mount, Workpiece Mount, Geometry Anchor anchor required
Workpiece Fixture Mount, Program-Zero Anchor, Geometry Anchor anchor required
Check Meaning
Unbound Not bound; the mechanism needs this role.
NotOwn Bound to an element outside this mechanism's own assembly.
Duplicate The same element also plays {other}.
NotReachable No branch chain leads from the root anchor to this anchor.
AxisTransformerMismatch Needs a {expected} branch; the bound branch carries {actual}.
AxisOffChain The branch is not on the chain between the table mount and the tool mount.

Canvas Display Option

The shared Equipment canvas's Display Options dropdown carries a Role Anchors flag in its Anchors group (show-role-anchors, off by default): it draws the axes of every bound role anchor — the machine's two mounts, the fixture's three anchors, the workpiece's three — independently of the per-anchor flags. An anchor the machine does not reach is not placed and draws nothing.

Behavior

  • Arm and pick. The arm button on a Roles row arms that role (the chip appears in a strip above the graph), and a second click on it disarms. The next click on a graph element of the same kind that belongs to the same part binds it, toasts "{role} bound.", disarms and refreshes; an element of the wrong kind repeats the armed hint, and an element of another part toasts “That element belongs to another part; pick one from the part that owns the role.” and leaves the role armed. The select on the row binds without arming; clearing it unbinds. A refused bind leaves the select on the bound element.
  • After every edit — a bind, a rename, an anchor or branch created or deleted, a transformer swapped, a solid hung — the server rewires the equipment's attachments (Rewire), regenerates the machine's collision pairs when the machine auto-generates them and both its mounts are bound, and notifies the project so the runtime face follows; the canvas redraws on its next frame. The attachment branches are re-minted by every rewire, so the column re-pulls the graph and the roles (reinitializeMechanism / refreshTopology on the Control-Tree host) rather than patching them, and a selected worktable attachment follows its new guid. Calls that leave the topology unchanged — has-geom, geom-type, the rgb read and write, refresh-geom-cache, index-transformer — settle nothing; index-geom does so only when it hung a new solid.
  • An in-place value edit inside the branch card's transformer editor re-posts update-transformer with the same key, so the object the switchboard produced is the one installed on the branch when the redraw happens; inside the anchor card's geometry editor it posts refresh-geom-cache, so the runtime face — which shares the solid instance — re-triangulates. Either then refreshes the graph; a geometry kind switch is structural and goes through the host's re-pull instead.
  • Edits are serialised on one promise chain; while one is in flight — the column's own, or a bind from a Roles panel's select — the graph ignores clicks; the title bar's Refresh and the card's Extend, Delete, Add Branch select, Geometry checkbox and colour controls are disabled, and so are the Roles panels' selects and arm buttons. The transformer and geometry editors in the card are not gated: a kind switch in either queues behind the edit in flight. The name fields stay editable too: a rename committed meanwhile queues behind the edit in flight. The state — graph, roles, selection, armed role — is one module singleton shared by the column and the three Roles panels, so the Control-Tree host's own refresh after Load / Paste / New on a mechanism item updates the column too.
  • The column pulls the graph and the roles when it mounts, which it does even while hidden, since a hidden column is pinned to 0 px rather than unmounted. A pull the column wants while hidden — its state emptied under it — waits until it is shown on the active page; the host's re-pulls after a bind or a Load / Paste / New run either way. A no-project 404 is an empty state, not an error.

HTTP Surface

Everything is under api/mech/equipment-topology. Owners are machine-tool, fixture and workpiece; equipment is accepted only by the two branch-transformer routes, and only for the worktable attachment. A POST body is JSON.

Route Does
GET graph?toolInternals= The whole equipment as one graph; toolInternals=true adds the tool's own anchors and branches (the page never asks for them)
GET roles, GET roles/{owner} The roles of every part / one part, with candidates and checks
POST roles/{owner}/{role} body { "guid": "…" } Binds the role to the part's own element; an empty guid unbinds; answers the part's roles
POST {owner}/asmb/{id}/rename body { "name": "…" } Renames the part's key assembly or one below it; 400 for a name carrying the path separator, opening like a GUID segment, or worn by a sibling assembly
POST {owner}/anchor/new?name= A stand-alone anchor in the part's key assembly
POST {owner}/anchor/extend-from/{id} A new anchor downstream of {id} on a NoTransform branch
POST {owner}/anchor/{id}/rename body { "name": "…" } Renames
DELETE {owner}/anchor/{id} Deletes the anchor and its branches; answers { success, unboundRoles }; the root is refused
POST {owner}/branch body { "fletchAnchorGuid", "arrowAnchorGuid" } A NoTransform branch between two anchors of the part
POST {owner}/branch/{id}/rename Renames
DELETE {owner}/branch/{id} Deletes; answers unboundRoles
POST {owner}/branch/{id}/index-transformer Indexes the branch's transformer; answers its key
POST {owner}/branch/{id}/update-transformer?transformerKey= Swaps the branch's transformer to the indexed one; answers the canonical key
GET {owner}/anchor/{id}/has-geom, GET …/geom-type, GET …/rgb The anchor solid's presence, geometry type name (or None), display colour
POST {owner}/anchor/{id}/enable-geom, …/disable-geom Hangs a solid holding an empty TransformationGeom (an existing solid is kept), which the card presents as a slot with no kind yet / removes it
POST {owner}/anchor/{id}/index-geom Indexes the solid's geometry for the editor, hanging a solid first when there is none; answers the key
POST {owner}/anchor/{id}/create-geom?geometryType= A fresh geometry of that kind on the solid (None clears it)
POST {owner}/anchor/{id}/set-geom-transform?transformerType= Wraps the solid's geometry in a TransformationGeom of that transformer kind, swaps the transformer, or with None unwraps it — in place, the authored geometry kept; what the card's Transform picker posts; 409 on an anchor without a solid or a solid holding nothing
POST {owner}/anchor/{id}/refresh-geom-cache Clears the solid's cached triangulation after an in-place edit
POST {owner}/anchor/{id}/rgb?rgb= Authors the display colour (#rrggbb; empty clears)

IndexService keys: a branch transformer is equipment-topology.<owner>.branch.<guid>.transformer, an anchor solid's geometry equipment-topology.<owner>.anchor.<guid>.geom (the guid written without hyphens in both); the worktable attachment's is equipment-topology.equipment.table-to-comp.

Status code When
404 NoProjectLoaded No project, or no authored equipment
400 UnknownOwner An owner other than the three parts (tool included)
404 MechanismNotFound The owner names a part the project has not mounted
409 MechanismNotEditable The machine tool is a ClMillingDevice
404 RoleNotFound The part has no role of that key
409 RoleElementTaken The element already plays another role of the same part
409 AxisTransformerMismatch An axis role given a branch of the wrong kind, or an axis branch given the wrong transformer
409 MechanismRefused The part's own rule: a role takes only an element of its assembly
409 SolidsNotAllowed enable-geom, disable-geom, index-geom or create-geom on the workpiece (its read routes answer as for an anchor with no solid)
404 AsmbNotFound An assembly guid outside the part's key assembly
404 AnchorNotFound An anchor guid outside the part's key assembly
404 BranchNotFound A branch guid outside the part's key assembly, or, under owner equipment, a guid that names no branch of the equipment
409 AttachmentFixed Owner equipment on any branch other than the worktable attachment (another attachment, or a part's own branch)
409 GeomAnchorKeepsItsSolid disable-geom on the fixture's Geometry Anchor

The program-zero alignment stays on the Controller: POST /api/Controller/iso-coordinate-table/{index}/align-workpiece-program-zero and POST /api/Controller/iso-coordinate-table/revert-align-workpiece-program-zero rewrite the transformer of the fixture branch that leads from its Geometry Anchor straight to its Table Mount.

Default Topology

A part built by CreateDefault — which is also the shape every legacy-form file loads onto — is what the graph shows on a fresh project. Fixture: the root is the Geometry Anchor, carrying the fixture's solid, with one NoTransform branch to the Table Mount and one to the Workpiece Mount, each branch named after the mount it reaches. Workpiece: the root is the Fixture Mount; from the Geometry Anchor one zero StaticTranslation branch leads to the Fixture Mount and one to the Program-Zero Anchor, each named after the anchor it reaches. A mission script addresses the same branches: once the fixture's table branch carries a StaticTranslation (the program-zero alignment writes one; the default shape's is NoTransform), (Branch.Get(Fixture.GeomAnchor, Fixture.TableMount).Transformer as StaticTranslation).Trans += new vec3d_t(0, 0, …);, and Branch.Get(Workpiece.GeomAnchor, Workpiece.ProgramZeroAnchor).Transformer = transform;.

Source Code Path

See HiNC App Anatomy for git repository links.

Web Application

HiNC-2025-webservice (Quasar CLI SPA):

  • wwwroot-src/src/components/mech/EquipmentTopologyPanel.vue — the column: the Refresh button it teleports onto the title bar, the armed-role strip, the graph, the height divider and the editor card, addressed by owner; the arm-and-pick bind; the serialised edit chain and the post-edit refresh.
  • wwwroot-src/src/components/mech/MechanismRolesPanel.vue — the Roles panel a mechanism root panel ends with: the rows, the candidate selects, the arm buttons and the checks list.
  • wwwroot-src/src/components/mech/MechBuilderGraph.vue — the graph view, its name historical: nested assembly clusters, role badges, dotted attachment edges, and the anchor / branch / cluster click delegation; the direction, zoom and fit-width toolbar, drag-to-pan, and the scroll a redraw keeps. Mermaid is dynamic-imported on first draw, and every label is emitted quoted, which the parser requires for CJK text.
  • wwwroot-src/src/composables/useEquipmentTopology.ts — the module singleton: the graph and roles, the exclusive selection, the armed role, the refresh epoch and the worktable-attachment test.
  • wwwroot-src/src/api/equipmentTopology.ts — typed client for api/mech/equipment-topology: the owner types, the graph and roles DTOs, and one function per route.
  • wwwroot-src/src/components/controlTree/useControlTreeHost.ts — reinitializeMechanism / refreshTopology: the re-pull after a bind, an edit, or a Load / Paste / New on a mechanism item; and the topology reset in the equipment host's setup, once per project epoch, before the column mounts and pulls.
  • wwwroot-src/src/components/controlTree/PrimarySlavePanel.vue — mounts the Roles panel at the end of each of the three inline mechanism root panels.
  • wwwroot-src/src/pages/EquipmentPage.vue — the four-column host: the reversed pixel splitter that gives the column its own width, the canvas-hidden hand-over, and the column's title bar with the controls container the panel's Refresh button lands in.
  • wwwroot-src/src/components/AppMenuBar.vue — the column-button row, whose fourth button on this page toggles the column.
  • wwwroot-src/src/composables/useViewPrefs.ts — the topology column bit, its window-width first-run default, topologyColPx, and topologyGraphPx, the graph's height above the card.
  • wwwroot-src/src/router/treeRoutes.ts — the retired-slot hop: a legacy ?tree= link into a mechanism item's former child ids lands on that item.
  • wwwroot-src/src/components/topo/TransformerSelectPanel.vue and wwwroot-src/src/components/geom/GeometryEditor.vue — the switchboards the branch and anchor cards mount.
  • wwwroot-src/src/components/mech/EquipmentSetupPanel.vue and wwwroot-src/src/api/equipmentSetup.ts — the Role Anchors flag on the shared canvas's Display Options.
  • wwwroot-src/src/i18n/en/mech.ts — the topology.* and roles.* labels, and the canvas flag.
  • Mech/Topology/EquipmentTopologyController.cs — the REST surface: owner resolution, the graph and roles reads, the anchor / branch / solid routes, the worktable-attachment gate, and the after-edit settle (rewire, collision pairs, notify).
  • Mech/Topology/EquipmentRoles.cs — the per-part role table, Describe (roles, candidates, checks), the six checks, Bind with its two refusals, Unbind before a delete, and the axis-transformer guard.
  • Mech/Topology/TopologyEditService.cs — anchor / branch CRUD, transformer indexing and swap, solid enable / index / create / type / cache / colour on any mechanism, built per request by the controller above with the equipment-topology.<owner> key prefix.
  • Mech/Topology/TopologyGraphDto.cs and Mech/Topology/TopologyGraphBuilder.cs — the graph DTO (assemblies, anchors, branches, root anchor id, mechanisms) and how owners, attachments and the tool-internals cut are decided.
  • Common/ApiError.cs — the error codes above.
  • Disp/EquipmentSetupDisplayeeConfig.cs, Disp/EquipmentSetupDisplayee.cs and Mech/EquipmentSetupDisplayController.cs — ShowRoleAnchors: the persisted flag, the drawing, and its show-role-anchors/{renderingConnectionId} endpoint.
  • Controller/ControllerController.cs — the align / revert-align endpoints that write the fixture's table branch.

HiAPI Engine

  • HiMech/NcMech/Xyzabc/GeneralXyzabcMachineTool.cs — the machine's own topology and roles: TableMount, ToolMount, AxisX … AxisC, Spindle.
  • HiMech/NcMech/Fixtures/Fixture.cs — the fixture's assembly, its three anchor roles, Solid / Geom on the Geometry Anchor, HangSolid and CreateDefault.
  • HiMech/NcMech/Workpieces/Workpiece.cs — the workpiece's assembly, its three anchor roles and CreateDefault.
  • HiMech/Machining/MachiningEquipmentUtils/EquipmentWiring.cs — Rewire: the attachment branches detached and re-attached whole from the parts' current roles.
  • HiMech/Machining/MachiningEquipmentUtils/MachiningEquipmentUtil.cs — TryAlignWorkpieceProgramZeroToIso, the alignment the Controller endpoints call.

See Also

  • Equipment Page — the page this column belongs to
  • Machine Tool — the part whose mounts and axes are bound on its root panel and authored here
  • Fixture — the part whose Geometry Anchor carries a solid and whose table branch the program-zero alignment writes
  • Workpiece — the part whose anchors carry no solids, and whose Program-Zero Anchor a script addresses through this graph
  • Transformer Select Panel — the switchboard the branch card mounts, and the parent-aware swap it performs
  • Geometry Editor — the switchboard the anchor card mounts over the anchor solid's geometry
  • Control Tree — the host whose reinitializeMechanism re-pulls this column after an edit, and whose mechanism items a cluster click selects
  • Tree Ids and Routes — why this column has no ?tree= id, and the hop that lands retired mechanism child ids on their item
  • Main Panel — the menu bar whose last column toggle on this page shows and hides the column
  • Anchors and Roles — the end-user placement task done through this column and the Roles panels
  • Object Store (IndexService) — the keyed store the branch transformers and anchor geometries are edited through
  • Driving the Web Service over HTTP — the same routes driven by a script