Skip to content

Commit cc29437

Browse files
Merge pull request #6081 from mermaid-js/6080-fix
fix: Elk rendering of Diamond shape intersections
2 parents dfaaf36 + 3753831 commit cc29437

File tree

4 files changed

+181
-38
lines changed

4 files changed

+181
-38
lines changed

Diff for: .changeset/nervous-beans-listen.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@mermaid-js/layout-elk': patch
3+
---
4+
5+
fix: Elk rendering of Diamond shape intersections

Diff for: cypress/integration/rendering/flowchart-elk.spec.js

+43
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,49 @@ flowchart LR
857857
D --> E
858858
A["A"]
859859
860+
`,
861+
{ flowchart: { titleTopMargin: 0 } }
862+
);
863+
});
864+
it('6080: should handle diamond shape intersections', () => {
865+
imgSnapshotTest(
866+
`---
867+
config:
868+
layout: elk
869+
---
870+
flowchart LR
871+
subgraph s1["Untitled subgraph"]
872+
n1["Evaluate"]
873+
n2["Option 1"]
874+
n3["Option 2"]
875+
n4["fa:fa-car Option 3"]
876+
end
877+
subgraph s2["Untitled subgraph"]
878+
n5["Evaluate"]
879+
n6["Option 1"]
880+
n7["Option 2"]
881+
n8["fa:fa-car Option 3"]
882+
end
883+
A["Start"] -- Some text --> B("Continue")
884+
B --> C{"Evaluate"}
885+
C -- One --> D["Option 1"]
886+
C -- Two --> E["Option 2"]
887+
C -- Three --> F["fa:fa-car Option 3"]
888+
n1 -- One --> n2
889+
n1 -- Two --> n3
890+
n1 -- Three --> n4
891+
n5 -- One --> n6
892+
n5 -- Two --> n7
893+
n5 -- Three --> n8
894+
n1@{ shape: diam}
895+
n2@{ shape: rect}
896+
n3@{ shape: rect}
897+
n4@{ shape: rect}
898+
n5@{ shape: diam}
899+
n6@{ shape: rect}
900+
n7@{ shape: rect}
901+
n8@{ shape: rect}
902+
860903
`,
861904
{ flowchart: { titleTopMargin: 0 } }
862905
);

Diff for: cypress/platform/knsv2.html

+118-24
Original file line numberDiff line numberDiff line change
@@ -88,40 +88,134 @@
8888
</head>
8989

9090
<body>
91-
<pre id="diagram4" class="mermaid">
91+
<pre id="diagram4" class="mermaid2">
9292
---
9393
config:
94-
look: handDrawn
95-
theme: default
94+
layout: elk
9695
---
9796
flowchart LR
98-
n00@{ shape: triangle, label: 'This is a label for triangle shape' }
99-
n11@{ shape: sloped-rectangle, label: 'This is a label for sloped-rectangle shape' }
100-
n22@{ shape: horizontal-cylinder, label: 'This is a label for horizontal-cylinder shape' }
101-
n33@{ shape: flipped-triangle, label: 'This is a label for flipped-triangle shape' }
102-
n44@{ shape: hourglass, label: 'This is a label for hourglass shape' }
103-
n00 --> n11
104-
n00 --> n22
105-
n00 --> n33
106-
n00 --> n44
107-
n11 --> n22
108-
n11 --> n33
109-
n11 --> n44
110-
n22 --> n33
111-
n22 --> n44
112-
n33 --> n44
97+
subgraph s1["Untitled subgraph"]
98+
n1["Evaluate"]
99+
n2["Option 1"]
100+
n3["Option 2"]
101+
n4["fa:fa-car Option 3"]
102+
end
103+
n1 -- One --> n2
104+
n1 -- Two --> n3
105+
n1 -- Three --> n4
106+
n5
107+
n1@{ shape: diam}
108+
n2@{ shape: rect}
109+
n3@{ shape: rect}
110+
n4@{ shape: rect}
111+
A["Start"] -- Some text --> B("Continue")
112+
B --> C{"Evaluate"}
113+
C -- One --> D["Option 1"]
114+
C -- Two --> E["Option 2"]
115+
C -- Three --> F["fa:fa-car Option 3"]
116+
117+
113118
</pre>
114119
<pre id="diagram4" class="mermaid">
115120
---
116121
config:
117-
look: handDrawn
118-
theme: default
122+
layout: elk
123+
---
124+
flowchart LR
125+
subgraph s1["Untitled subgraph"]
126+
n1["Evaluate"]
127+
n2["Option 1"]
128+
n3["Option 2"]
129+
n4["fa:fa-car Option 3"]
130+
end
131+
subgraph s2["Untitled subgraph"]
132+
n5["Evaluate"]
133+
n6["Option 1"]
134+
n7["Option 2"]
135+
n8["fa:fa-car Option 3"]
136+
end
137+
A["Start"] -- Some text --> B("Continue")
138+
B --> C{"Evaluate"}
139+
C -- One --> D["Option 1"]
140+
C -- Two --> E["Option 2"]
141+
C -- Three --> F["fa:fa-car Option 3"]
142+
n1 -- One --> n2
143+
n1 -- Two --> n3
144+
n1 -- Three --> n4
145+
n5 -- One --> n6
146+
n5 -- Two --> n7
147+
n5 -- Three --> n8
148+
n1@{ shape: diam}
149+
n2@{ shape: rect}
150+
n3@{ shape: rect}
151+
n4@{ shape: rect}
152+
n5@{ shape: diam}
153+
n6@{ shape: rect}
154+
n7@{ shape: rect}
155+
n8@{ shape: rect}
156+
157+
</pre>
158+
<pre id="diagram4" class="mermaid2">
159+
---
160+
config:
161+
layout: elk
162+
---
163+
flowchart LR
164+
subgraph s1["Untitled subgraph"]
165+
n1["Evaluate"]
166+
n2["Option 1"]
167+
end
168+
n1 -- One --> n2
169+
170+
171+
172+
173+
</pre>
174+
<pre id="diagram4" class="mermaid2">
175+
---
176+
config:
177+
layout: elk
119178
---
120179
flowchart LR
121-
n22@{ shape: h-cyl }
122-
n00 --> n11
123-
n00 --> n22
124-
n11 --> n22
180+
A{A} --> B & C
181+
</pre
182+
>
183+
<pre id="diagram4" class="mermaid2">
184+
---
185+
config:
186+
layout: elk
187+
---
188+
flowchart LR
189+
n2@{ shape: rect}
190+
n3@{ shape: rect}
191+
n4@{ shape: rect}
192+
A["Start"] -- Some text --> B("Continue")
193+
B --> C{"Evaluate"}
194+
C -- One --> D["Option 1"]
195+
C -- Two --> E["Option 2"]
196+
C -- Three --> F["fa:fa-car Option 3"]
197+
%% C@{ shape: hexagon}
198+
199+
200+
</pre>
201+
<pre id="diagram4" class="mermaid2">
202+
---
203+
config:
204+
kanban:
205+
ticketBaseUrl: 'https://github.com/your-repo/issues/#TICKET#'
206+
---
207+
kanban
208+
Backlog
209+
task1[📝 Define project requirements]@{ ticket: a101 }
210+
To Do
211+
task2[🔍 Research technologies]@{ ticket: a102 }
212+
Review
213+
task4[🔍 Code review for login feature]@{ ticket: a104 }
214+
Done
215+
task5[✅ Deploy initial version]@{ ticket: a105 }
216+
In Progress
217+
task3[💻 Develop login feature]@{ ticket: 103 }
218+
125219
</pre>
126220
<pre id="diagram4" class="mermaid2">
127221
flowchart LR

Diff for: packages/mermaid-layout-elk/src/render.ts

+15-14
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,8 @@ export const render = async (
484484
const r3 = a1 * q1.x + b1 * q1.y + c1;
485485
const r4 = a1 * q2.x + b1 * q2.y + c1;
486486

487+
const epsilon = 1e-6;
488+
487489
// Check signs of r3 and r4. If both point 3 and point 4 lie on
488490
// same side of line 1, the line segments do not intersect.
489491
if (r3 !== 0 && r4 !== 0 && sameSign(r3, r4)) {
@@ -502,7 +504,7 @@ export const render = async (
502504
// Check signs of r1 and r2. If both point 1 and point 2 lie
503505
// on same side of second line segment, the line segments do
504506
// not intersect.
505-
if (r1 !== 0 && r2 !== 0 && sameSign(r1, r2)) {
507+
if (Math.abs(r1) < epsilon && Math.abs(r2) < epsilon && sameSign(r1, r2)) {
506508
return /*DON'T_INTERSECT*/;
507509
}
508510

@@ -547,11 +549,11 @@ export const render = async (
547549
{ x: x1 - w / 2, y: y1 },
548550
];
549551
log.debug(
550-
`UIO diamondIntersection calc abc89:
552+
`APA16 diamondIntersection calc abc89:
551553
outsidePoint: ${JSON.stringify(outsidePoint)}
552554
insidePoint : ${JSON.stringify(insidePoint)}
553-
node : x:${bounds.x} y:${bounds.y} w:${bounds.width} h:${bounds.height}`,
554-
polyPoints
555+
node-bounds : x:${bounds.x} y:${bounds.y} w:${bounds.width} h:${bounds.height}`,
556+
JSON.stringify(polyPoints)
555557
);
556558

557559
const intersections = [];
@@ -564,17 +566,17 @@ export const render = async (
564566
minY = Math.min(minY, entry.y);
565567
});
566568

567-
// const left = x1 - w / 2;
568-
// const top = y1 + h / 2;
569+
const left = x1 - w / 2 - minX;
570+
const top = y1 - h / 2 - minY;
569571

570572
for (let i = 0; i < polyPoints.length; i++) {
571573
const p1 = polyPoints[i];
572574
const p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0];
573575
const intersect = intersectLine(
574576
bounds,
575577
outsidePoint,
576-
{ x: p1.x, y: p1.y },
577-
{ x: p2.x, y: p2.y }
578+
{ x: left + p1.x, y: top + p1.y },
579+
{ x: left + p2.x, y: top + p2.y }
578580
);
579581

580582
if (intersect) {
@@ -753,7 +755,6 @@ export const render = async (
753755
}
754756
}
755757
});
756-
log.debug('returning points', points);
757758
return points;
758759
};
759760

@@ -968,17 +969,17 @@ export const render = async (
968969
startNode.innerHTML
969970
);
970971
}
971-
if (startNode.shape === 'diamond') {
972+
if (startNode.shape === 'diamond' || startNode.shape === 'diam') {
972973
edge.points.unshift({
973974
x: startNode.x + startNode.width / 2 + offset.x,
974975
y: startNode.y + startNode.height / 2 + offset.y,
975976
});
976977
}
977-
if (endNode.shape === 'diamond') {
978+
if (endNode.shape === 'diamond' || endNode.shape === 'diam') {
978979
const x = endNode.x + endNode.width / 2 + offset.x;
979980
// Add a point at the center of the diamond
980981
if (
981-
Math.abs(edge.points[edge.points.length - 1].y - endNode.y - offset.y) > 0.001 ||
982+
Math.abs(edge.points[edge.points.length - 1].y - endNode.y - offset.y) > 0.01 ||
982983
Math.abs(edge.points[edge.points.length - 1].x - x) > 0.001
983984
) {
984985
edge.points.push({
@@ -997,7 +998,7 @@ export const render = async (
997998
height: startNode.height,
998999
padding: startNode.padding,
9991000
},
1000-
startNode.shape === 'diamond'
1001+
startNode.shape === 'diamond' || startNode.shape === 'diam'
10011002
).reverse();
10021003

10031004
edge.points = cutPathAtIntersect(
@@ -1009,7 +1010,7 @@ export const render = async (
10091010
height: endNode.height,
10101011
padding: endNode.padding,
10111012
},
1012-
endNode.shape === 'diamond'
1013+
endNode.shape === 'diamond' || endNode.shape === 'diam'
10131014
);
10141015

10151016
const paths = insertEdge(

0 commit comments

Comments
 (0)