Skip to content

Commit f866e81

Browse files
Copilotjongalloway
andcommitted
Fix chevron diagram shape: inward V-notch with overlap layout
Non-first chevron nodes were incorrectly protruding leftward (<> shape). Fix uses an inward V-notch polygon and overlapping layout so each node's right tip aligns exactly with the next node's notch. Co-authored-by: jongalloway <68539+jongalloway@users.noreply.github.com>
1 parent c67624d commit f866e81

4 files changed

Lines changed: 20 additions & 14 deletions

File tree

src/DiagramForge/Layout/DefaultLayoutEngine.Chevron.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ private static void LayoutChevronDiagram(
3737
{
3838
var node = orderedNodes[index];
3939

40-
// Zero gap: bounding boxes abut so the tip of stage N meets the notch of stage N+1.
41-
node.X = pad + index * nodeW;
40+
// Overlap layout: each stage overlaps the previous by tipDepth so the right tip of
41+
// stage N aligns exactly with the inward notch of stage N+1.
42+
node.X = pad + index * (nodeW - tipDepth);
4243
node.Y = pad + titleOffset;
4344
node.Width = nodeW;
4445
node.Height = nodeH;

src/DiagramForge/Rendering/SvgNodeWriter.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,12 @@ private static void AppendChevronNode(StringBuilder sb, Node node, string fill,
241241
double midY = h / 2;
242242

243243
// First chevron: flat left edge, pointed right – 5 points (pentagon).
244-
// Subsequent chevrons: notched left edge matching previous arrow point, pointed right – 6 points (hexagon).
244+
// Subsequent chevrons: inward V-notch on left matching previous arrow tip, pointed right – 6 points (hexagon).
245+
// The notch vertex at (tipDepth, midY) aligns with the tip of the preceding stage because
246+
// the layout overlaps bounding boxes by tipDepth.
245247
string points = index == 0
246248
? $"0,0 {SvgRenderSupport.F(w - tipDepth)},0 {SvgRenderSupport.F(w)},{SvgRenderSupport.F(midY)} {SvgRenderSupport.F(w - tipDepth)},{SvgRenderSupport.F(h)} 0,{SvgRenderSupport.F(h)}"
247-
: $"0,{SvgRenderSupport.F(midY)} {SvgRenderSupport.F(tipDepth)},0 {SvgRenderSupport.F(w - tipDepth)},0 {SvgRenderSupport.F(w)},{SvgRenderSupport.F(midY)} {SvgRenderSupport.F(w - tipDepth)},{SvgRenderSupport.F(h)} {SvgRenderSupport.F(tipDepth)},{SvgRenderSupport.F(h)}";
249+
: $"0,0 {SvgRenderSupport.F(w - tipDepth)},0 {SvgRenderSupport.F(w)},{SvgRenderSupport.F(midY)} {SvgRenderSupport.F(w - tipDepth)},{SvgRenderSupport.F(h)} 0,{SvgRenderSupport.F(h)} {SvgRenderSupport.F(tipDepth)},{SvgRenderSupport.F(midY)}";
248250

249251
sb.AppendLine($""" <polygon points="{points}" fill="{fill}" stroke="{stroke}" stroke-width="{SvgRenderSupport.F(theme.StrokeWidth)}"{fillOpacityAttribute}{shadowAttribute}/>""");
250252
}

tests/DiagramForge.E2ETests/Fixtures/conceptual-chevrons.expected.svg

Lines changed: 8 additions & 8 deletions
Loading

tests/DiagramForge.Tests/Layout/DefaultLayoutEngineTests.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,8 +1362,11 @@ public void Layout_Chevrons_AdjacentNodesAreImmediatelyAbutted()
13621362
var first = diagram.Nodes["node_0"];
13631363
var second = diagram.Nodes["node_1"];
13641364

1365-
// Zero gap: the tip of stage 0 meets the notch of stage 1 at their shared boundary.
1366-
Assert.Equal(first.X + first.Width, second.X, precision: 6);
1365+
// Overlap layout: the right tip of stage 0 aligns with the inward notch of stage 1.
1366+
// second.X is inset by tipDepth so the tip (first.X + first.Width) coincides with
1367+
// the notch vertex (second.X + tipDepth).
1368+
double tipDepth = (double)second.Metadata["conceptual:chevronTipDepth"];
1369+
Assert.Equal(first.X + first.Width, second.X + tipDepth, precision: 6);
13671370
}
13681371

13691372
[Fact]

0 commit comments

Comments
 (0)