Repository navigation
VC3D: link fibers in two gestures (Fiber Map "Link A and B", in-dialog link from a fiber-intersection X) - #2217
Merged
Merged
Conversation
…omatic links) Linking two fibers used to take four menus and two dialog opens. The Fiber Map now does it in two gestures: - Selection: Shift+left click keeps the last two clicked fibers selected (a plain click selects one); both draw bold with their control dots and the status line names the pair; a rebuild keeps the pair. - Ctrl+right-click on either selected fiber adds "Link <A> and <B>" above Delete. It finalizes, saves and closes any open annotation of the two fibers (D8), locates the meeting on the drawn map (the crossing nearest the click, else the closest approach within 1 mm; D2), inverts it exactly to a position on each fiber's stored line through the unrolled arclength the map was drawn with (Run::arclengths), searches the fibers' closest 3D pass only within +-5 mm along each fiber (D3), reuses an UNLINKED control within 1 mm or places a new one clear of every control by the strip's minimum spacing, not beyond a kollesis termination, not in a gap span, inside the focus bounds, re-optimizing the two spans synchronously and saving (D4), never refusing on the 3D gap (D5), and links the two controls with a pending AUTOMATIC link whose pair save is drained before success is reported. - Format (D6): "auto": true next to "pending": true on ordinary links, mirrored on both reciprocal refs and by scripts/fiber_merge.py; the loader downgrades a one-sided mark to plain pending on both sides; combining two refs (collapse, dedup, merge) is automatic only if every pending contributor was; approval clears it. - Markers (D7): an automatic pending point draws with its own look everywhere a linked point is drawn (cut views and strips in both renderers, overview bar, slice-view rings, Fiber Map dots); a tagged point keeps its tag ring; a human-made pending link on the same point outranks. Robustness, from the review rounds folded into this commit: the controller's auto-link is guarded after every yield (package, load sequence, volume, fiber generation, save failures, focus bounds, map dependencies, open panes, running solves), re-resolves stored fibers after each, validates control identity before and after each solve, reads a saved control back before any verdict, tracks the installed link's endpoints through moves (TrackedLinkEndpoints) so a failed pair write withdraws every copy (stored records, queued snapshots, open sessions and their rollback copies) and re-saves the withdrawn state, holds the structural-edit guard for its duration, and keeps an operation message on the map's status line across staleness refreshes. The geometry is exact (accurate cross products, exact window clipping, representable boundary candidates, strict spacing gate). A reload's downgrade reaches open sessions. Tests: apps/VC3D/test/ test_fiber_map_auto_link.cpp, the global-layout and link-validation tests, scripts/tests/test_fiber_merge.py. Docs: "Linking two fibers from the Fiber Map" in docs/line_annotation_fibers.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PrhaQ58LygRfA7y3Psp7uf
Phase B finalized every open Line Annotation dialog and every save bumps the fiber generation, so any open annotation made the map stale and Link had to be chosen twice. Now only dialogs of the two fibers are finalized (prepareForUserFacingLineAnnotationOpen takes a session filter), and when a save did make the map stale the workspace keeps the request (_autoLinkResume: the pair, the click, the two fibers' drawn geometry captured before phase B) and runs it again by itself once the automatic Update publishes, provided both fibers draw exactly as the click saw them and the layout is fresh; otherwise the status line asks for Link again. A cancellation token covers the queued callback and a click inside phase B's own drains; cancelling clears the promise. Also carried here (replaced by the palette commit after the merge): an interim paler fill for automatic pending markers. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PrhaQ58LygRfA7y3Psp7uf
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Conflict resolutions (all against the changes main carried since the branch point; the later main commits touch none of this branch's files): - FiberNetworkLayout: both sides' additions kept (branch: Run::arclengths, PlacedFiber::controlArclength/thetaScale/offsetRad; main: worldPoints, controlWorldPoints, trimDisplayRun). - FiberMapWorkspace: the branch's endpoint-dot drawer kept, main's updateFocusBounds() call kept after it. - LineAnnotationController.hpp: main's removal of scaleStoredFiber and its fiberToJson/saveFiberNow/makeFiberSaveSnapshot signatures taken; the branch's TrackedLinkEndpoints and stillValid parameters kept. - handleGeneratedControlPoint: main's break tag for a control placed beyond a lone end break (appendedControlToTagAsBreak) now lives in the shared applyGeometricControlPointEdit, so the interactive handler and the auto-link's placement apply the same rule. - finalizeSessionOptimizationSynchronously: main's single-control finalization (singleControlRayOnly, the Lasagna fallback for a single control without trace inputs) merged into ensureSessionSolveBackends (out-parameter solveAsLasagna) and runFiberModeSolveSynchronously (solveAsLasagna request override). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PrhaQ58LygRfA7y3Psp7uf
The merged single-control Lasagna fallback in ensureSessionSolveBackends is taken only by a caller with the out-parameter (the finalizer); any other caller, the auto-link's pre-placement check of a one-control fiber included, ensures the trace inputs as it did before the merge. A fresh verdict that reverts staleness retries a waiting resume (freshness can return without a publication), and a resume cancelled while its callback is queued clears the continuation promise. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PrhaQ58LygRfA7y3Psp7uf
…yan, pink) Replaces the dashed outline and the paler fill: an unreviewed automatic link draws solid like every other link state, bright cyan (#20f0ff) for an H/V link and light pink (#ffa8d8) for a same-H/V link (D9), everywhere a linked point is drawn and on the linked fiber's connector and projected X. One QtCore-free hue table (linkStateRgb) feeds every renderer, the Fiber Map palettes included; the separate rings, the tagged variants and the pale-fill helper are gone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PrhaQ58LygRfA7y3Psp7uf
…pers Pure geometry for the in-dialog "Link <current> and <other>" entry: generatedDrawnLineVertices (the renderer now builds its polyline runs from it, so the anchor rule and the screen agree on which segments exist), effectiveLineTailControlRange (the renderer's tail-range rule in one place), nearestDrawnLinePosition (the foot of a scene point on the nearest drawn, non-tail segment as a fractional line position) and autolink::nearestLinePosition (the foot of a 3D point over ALL segments of a polyline). Tests in the existing QtCore targets. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PrhaQ58LygRfA7y3Psp7uf
…withdrawal steps Mechanical extractions for the in-dialog automatic link, no behaviour change for the existing callers beyond the lifetime hardening noted: handleGeneratedControlPoint = prepareSessionForControlPlacement (the autosave flush and dataset yields, with lifetime, validity and the pane re-checked after each; the handler owns its session across them) + placeControlInSession (the tail over an edit whose collapse set the caller decided); materializeGeneratedViews takes an optional validity callback; handleGeneratedControlPointLinkWithCandidate's link body becomes linkSessionControlToStoredControl (both refs removed on a synchronous failure, the pane re-resolved after the publication); prepareFiberMapAutoLink becomes prepareAutoLinkParticipants over any participant set with one pane kept open; autoLinkFibers' choice step runs over plain data (planAutoLinkChoices), its placement over a prepared session is placePreparedControl, its withdrawal is withdrawTrackedLink; the map's preparation order is unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PrhaQ58LygRfA7y3Psp7uf
…section X The automatic link made from inside an open Line Annotation: Ctrl+right- click on another fiber's yellow X (current cut, side cut or strip) offers "Link A and B" directly under "Go to nearby annotation". The open fiber's control point is anchored at the pass of its DRAWN line nearest the X in that view (strip: the X's column; side cut: the nearest drawn non-tail segment of the windowed projection; current cut: the cut position), the other fiber's at the X; from those anchors the map's +-5 mm closest-pass search and 1 mm reuse rule decide the two controls (D10). The open fiber's new control is placed like a manual placement through the interactive tail with an empty collapse set (asynchronous span re-optimization, autosave, the same placement limit; the dialog stays open; D11); the other fiber's open dialog and dialog-less sessions are saved and closed first (D12); the link is a pending automatic link made right after the placement. Phase A in the slot verifies the identity captured when the menu opened (package, load sequence, volume, fiber generation), the anchor's line revision, the pair's eligibility and the placement limit, converts the X into base voxels only then, reserves the structural guard and defers the rest on a clean stack. Phases B-D retire the other fiber's sessions, run the choices over the live session and the stored record (one shared QtCore-free facts builder, autoLinkChoiceFacts, tested for parity), place the other fiber's control on a prepared detached session, place this fiber's through the shared tail, install the link through the shared session-link body, await its pair write (attributed by fiber generation, the link required still present in memory) and withdraw it on a failed write with the state re-saved. The guard distinguishes the stages (revision until placement, the placed control's identity until the install, the live-tracked link after); every yield - modals inside materialization and the metadata save included - is followed by its check. The disabled entry explains itself in a tooltip. Docs: "Linking from a fiber-intersection X". Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PrhaQ58LygRfA7y3Psp7uf
skyward7187
force-pushed
the
fiber-link-simplify
branch
from
October 22, 2026 02:52
6a05dfe to
7cabd72
Compare
hendrikschilling
approved these changes
Oct 22, 2026
hendrikschilling
enabled auto-merge (squash)
October 22, 2026 12:12
bruniss
added a commit
that referenced
this pull request
Oct 24, 2026
Upstream's fiber work is ported onto the object store instead of the resident fiber list and file save queue this branch removed. - "Link A and B" automatic links (#2217): the Fiber Map and in-dialog flows read fibers from the store after every yield, place controls through checked commits and make the link in one checked commit, so the tracked-link withdrawal and corrective re-save are gone. The automatic mark is `auto` in the fiber_branch edge metadata, only while the link is pending and ordinary; approval clears it. The store overlay draws the shared link palette (automatic cyan/pink, same-H/V warning, adjacent triangles). Fiber JSON transfer carries the mark. - vc_fiber_constraints reads AFV collections from an object store imported with import_afv.py (exact region selection, AFV ids kept); the vesuvius launcher imports each AFV once and passes the store. - fiber_merge.py and FiberOverlayController stay removed; upstream tests are adapted to the version-4 fiber contract and the dropped adjacentExplicit field. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
VC3D: link fibers in two gestures (Fiber Map "Link A and B", in-dialog link from a fiber-intersection X)
What
Linking two fibers used to take four menus and two dialog opens. This PR adds two short paths to the same automatic link, drawn in its own colour until approved.
From the Fiber Map
From an open Line Annotation
Look and format
"auto": truenext to"pending": trueon ordinary links, mirrored on both reciprocal refs;fiber_merge.pykeeps it in lockstep; the loader downgrades a one-sided mark to plain pending on both sides (an older VC3D resave strips it). Format notes indocs/line_annotation_fibers.mdanddocs/adjacent-fiber-links.html.Commits (8)
Review and tests
Design and code went through iterated codex (gpt-6-astra) reviews until READY: 14 plan rounds + 4 full + 4 specialist + 14 final code rounds for the map link; 6 plan + 4 full + 4 specialist + 1 final for the in-dialog link; the extractions were checked statement by statement against the pre-extraction code. Known limitation: no controller/dialog test harness exists, so the three-phase flows are covered by the GUI protocol below; the pure geometry (locator, closest pass, control choice, drawn-line anchor, choice facts) and the format/loader/merge rules have unit tests (
test_fiber_map_auto_link,test_fiber_global_layout,test_line_annotation_generated_views,test_line_annotation_link_validation,scripts/tests/test_fiber_merge.py).GUI protocol (PHerc0139 refinement project)
Proof
(screenshots)
🤖 Generated with Claude Code
https://claude.ai/code/session_01PrhaQ58LygRfA7y3Psp7uf