d2cycle: route "shape: cycle" edges as circular arcs clipped at shape borders - #2808
Open
kimotostudio wants to merge 1 commit into
Open
d2cycle: route "shape: cycle" edges as circular arcs clipped at shape borders#2808kimotostudio wants to merge 1 commit into
kimotostudio wants to merge 1 commit into
Conversation
… borders Fixes d2lang#1578 Generates cycle-layout edge routes analytically as cubic Bezier arc segments that start/stop exactly on shape borders (bounding box for rectangular shapes, Perimeter() for circle/hexagon/etc), so no renderer changes are needed. Snaps node positions to integers so export-time truncation cannot shift boxes off the float route endpoints. Guards single-node radius divergence and missing border crossings. Co-Authored-By: Claude Fable 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.
Fixes #1578
/claim #1578
Builds on the approach in #2362:
shape: cyclearranges objects in a circle and routes edges as perfectly circular arcs — and makes the arcs start/stop exactly on the shape borders while staying smooth. No renderer changes; measured worst endpoint-to-border distance 0.001px, anchor-radius spread 0.000px.How
Instead of sampling the arc as a polyline and clipping it afterwards (which fights the renderer's cubic-Bézier interpretation of
IsCurveroutes), the route is generated analytically:Perimeter(), matchingshape.TraceToShapeBordersemantics); non-rectangular shapes (circle, hexagon, ...) clip at their visiblePerimeter().k = 4/3·tan(Δθ/4), one segment per quarter turn), i.e. a[P0, C1, C2, P1, ...]route — sod2svg.pathDatarenders it as-is and no renderer changes are needed.int()truncation cannot shift boxes off the (float) route endpoints.Also guards the degenerate cases: single-node cycles no longer produce an infinite radius, and clipping falls back to the center-to-center arc if no border crossing is found.
Testing
TA=1 ./ci/test.sh ./e2etests -run TestE2E/txtar/cycle-diagram -v(the command from the bounty comment) generates the fixture; dagre + elk both pass. Measured from the generated boards: worst endpoint-to-border distance 0.001px, anchor-radius spread 0.000px (perfectly circular).d2layouts/d2cycle: border contact, circularity, non-rectangular perimeter clipping, single-node guard.CI=1 go test ./...passes with the repo's pinned toolchain (go1.25.0).cycle-diagrame2e fixture SVGs in this diff).Known limitations (happy to follow up): nested containers inside a cycle node keep their default layout (same as #2362), and outside labels/icons are not yet obstacles for the arc.
Disclosure: implemented with AI assistance (Claude), reviewed and submitted by me.