mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-28 07:03:17 +08:00
Merge pull request #1481 from mermaid-js/1474_missplaced_transitions
1474 missplaced transitions
This commit is contained in:
commit
98a7800fae
@ -4,15 +4,16 @@
|
|||||||
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
|
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
|
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||||
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
/* background: rgb(221, 208, 208); */
|
/* background: rgb(221, 208, 208); */
|
||||||
background:#333;
|
/* background:#333; */
|
||||||
font-family: 'Arial';
|
font-family: 'Arial';
|
||||||
}
|
}
|
||||||
h1 { color: white;}
|
h1 { color: grey;}
|
||||||
.mermaid2 {
|
.mermaid2 {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -20,44 +21,58 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>info below</h1>
|
<h1>info below</h1>
|
||||||
|
<div class="flex">
|
||||||
|
<div class="mermaid2" style="width: 50%; height: 20%;">
|
||||||
|
flowchart BT
|
||||||
|
subgraph two
|
||||||
|
b1
|
||||||
|
end
|
||||||
|
subgraph three
|
||||||
|
c1-->c2
|
||||||
|
end
|
||||||
|
c1 --apa apa apa--> b1
|
||||||
|
two --> c2
|
||||||
|
</div>
|
||||||
<div class="mermaid" style="width: 50%; height: 20%;">
|
<div class="mermaid" style="width: 50%; height: 20%;">
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
Alice->>Bob:Extremely utterly long line of longness which had preivously overflown the actor box as it is much longer than what it should be
|
Alice->>Bob:Extremely utterly long line of longness which had preivously overflown the actor box as it is much longer than what it should be
|
||||||
Bob->>Alice: I'm short though
|
Bob->>Alice: I'm short though
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mermaid2" style="width: 50%; height: 20%;">
|
<div class="mermaid2" style="width: 50%; height: 20%;">
|
||||||
flowchart TB
|
flowchart TB
|
||||||
subgraph 1
|
subgraph two
|
||||||
A --> B;
|
b1
|
||||||
A -.-> C;
|
end
|
||||||
A ==> D;
|
subgraph three
|
||||||
A ==> E;
|
c1-->c2
|
||||||
B <--> F
|
end
|
||||||
C <--> F
|
c1 --apa apa apa--> b1
|
||||||
D <--> F
|
b1 --> c2
|
||||||
E <--> F
|
</div>
|
||||||
end
|
<div class="mermaid" style="width: 50%; height: 20%;">
|
||||||
subgraph 2
|
|
||||||
A2 --x B2;
|
flowchart BT
|
||||||
A2 -.-x C2;
|
subgraph a
|
||||||
A2 ==x D2;
|
b1 -- ok --> b2
|
||||||
A2 ==x E2;
|
end
|
||||||
B2 x--x F2
|
a -- sert --> c
|
||||||
C2 x--x F2
|
c --> d
|
||||||
D2 x--x F2
|
b1 --> d
|
||||||
E2 x--x F2
|
a --asd123 --> d
|
||||||
end
|
</div>
|
||||||
subgraph 3
|
<div class="mermaid2" style="width: 50%; height: 20%;">
|
||||||
A3 --o B3;
|
stateDiagram-v2
|
||||||
A3 -.-o C3;
|
state A {
|
||||||
A3 ==o D3;
|
B1 --> B2: ok
|
||||||
A3 ==o E3;
|
}
|
||||||
B3 o--o F3
|
A --> C: sert
|
||||||
C3 o--o F3
|
C --> D
|
||||||
D3 o--o F3
|
B1 --> D
|
||||||
E3 o--o F3
|
A --> D: asd123
|
||||||
end
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mermaid2" style="width: 50%; height: 20%;">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="./mermaid.js"></script>
|
<script src="./mermaid.js"></script>
|
||||||
@ -66,7 +81,7 @@ flowchart TB
|
|||||||
// console.error('Mermaid error: ', err);
|
// console.error('Mermaid error: ', err);
|
||||||
};
|
};
|
||||||
mermaid.initialize({
|
mermaid.initialize({
|
||||||
theme: 'dark',
|
// theme: 'dark',
|
||||||
// arrowMarkerAbsolute: true,
|
// arrowMarkerAbsolute: true,
|
||||||
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
||||||
logLevel: 0,
|
logLevel: 0,
|
||||||
|
@ -2,6 +2,8 @@ import { logger } from '../logger'; // eslint-disable-line
|
|||||||
import createLabel from './createLabel';
|
import createLabel from './createLabel';
|
||||||
import { line, curveBasis, select } from 'd3';
|
import { line, curveBasis, select } from 'd3';
|
||||||
import { getConfig } from '../config';
|
import { getConfig } from '../config';
|
||||||
|
import utils from '../utils';
|
||||||
|
// import { calcLabelPosition } from '../utils';
|
||||||
|
|
||||||
let edgeLabels = {};
|
let edgeLabels = {};
|
||||||
|
|
||||||
@ -39,11 +41,19 @@ export const insertEdgeLabel = (elem, edge) => {
|
|||||||
edge.height = bbox.height;
|
edge.height = bbox.height;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const positionEdgeLabel = edge => {
|
export const positionEdgeLabel = (edge, points) => {
|
||||||
logger.info('Moving label', edge.id, edge.label, edgeLabels[edge.id]);
|
logger.info('Moving label', edge.id, edge.label, edgeLabels[edge.id]);
|
||||||
if (edge.label) {
|
if (edge.label) {
|
||||||
const el = edgeLabels[edge.id];
|
const el = edgeLabels[edge.id];
|
||||||
el.attr('transform', 'translate(' + edge.x + ', ' + edge.y + ')');
|
let x = edge.x;
|
||||||
|
let y = edge.y;
|
||||||
|
if (points) {
|
||||||
|
// debugger;
|
||||||
|
const pos = utils.calcLabelPosition(points);
|
||||||
|
x = pos.x;
|
||||||
|
y = pos.y;
|
||||||
|
}
|
||||||
|
el.attr('transform', 'translate(' + x + ', ' + y + ')');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -61,47 +71,80 @@ export const positionEdgeLabel = edge => {
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
const outsideNode = (node, point) => {
|
const outsideNode = (node, point) => {
|
||||||
|
// logger.warn('Checking bounds ', node, point);
|
||||||
const x = node.x;
|
const x = node.x;
|
||||||
const y = node.y;
|
const y = node.y;
|
||||||
const dx = Math.abs(point.x - x);
|
const dx = Math.abs(point.x - x);
|
||||||
const dy = Math.abs(point.y - y);
|
const dy = Math.abs(point.y - y);
|
||||||
const w = node.width / 2;
|
const w = node.width / 2;
|
||||||
const h = node.height / 2;
|
const h = node.height / 2;
|
||||||
if (dx > w || dy > h) {
|
if (dx >= w || dy >= h) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const intersection = (node, outsidePoint, insidePoint) => {
|
export const intersection = (node, outsidePoint, insidePoint) => {
|
||||||
logger.trace('intersection o:', outsidePoint, ' i:', insidePoint, node);
|
logger.warn('intersection calc o:', outsidePoint, ' i:', insidePoint, node);
|
||||||
const x = node.x;
|
const x = node.x;
|
||||||
const y = node.y;
|
const y = node.y;
|
||||||
|
|
||||||
const dx = Math.abs(x - insidePoint.x);
|
const dx = Math.abs(x - insidePoint.x);
|
||||||
const w = node.width / 2;
|
const w = node.width / 2;
|
||||||
let r = insidePoint.x < outsidePoint.x ? w - dx : w + dx;
|
let r = insidePoint.x < outsidePoint.x ? w - dx : w + dx;
|
||||||
const dy = Math.abs(y - insidePoint.y);
|
|
||||||
const h = node.height / 2;
|
const h = node.height / 2;
|
||||||
let q = insidePoint.y < outsidePoint.y ? h - dy : h - dy;
|
|
||||||
|
const edges = {
|
||||||
|
x1: x - w,
|
||||||
|
x2: x + w,
|
||||||
|
y1: y - h,
|
||||||
|
y2: y + h
|
||||||
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
outsidePoint.x === edges.x1 ||
|
||||||
|
outsidePoint.x === edges.x2 ||
|
||||||
|
outsidePoint.y === edges.y1 ||
|
||||||
|
outsidePoint.y === edges.y2
|
||||||
|
) {
|
||||||
|
// logger.warn('calc equals on edge');
|
||||||
|
return outsidePoint;
|
||||||
|
}
|
||||||
|
|
||||||
const Q = Math.abs(outsidePoint.y - insidePoint.y);
|
const Q = Math.abs(outsidePoint.y - insidePoint.y);
|
||||||
const R = Math.abs(outsidePoint.x - insidePoint.x);
|
const R = Math.abs(outsidePoint.x - insidePoint.x);
|
||||||
if (Math.abs(y - outsidePoint.y) * w > Math.abs(x - outsidePoint.x) * h || false) { // eslint-disable-line
|
// log.warn();
|
||||||
|
if (Math.abs(y - outsidePoint.y) * w > Math.abs(x - outsidePoint.x) * h) { // eslint-disable-line
|
||||||
// Intersection is top or bottom of rect.
|
// Intersection is top or bottom of rect.
|
||||||
|
// let q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y;
|
||||||
|
let q = insidePoint.y < outsidePoint.y ? outsidePoint.y - h - y : y - h - outsidePoint.y;
|
||||||
r = (R * q) / Q;
|
r = (R * q) / Q;
|
||||||
|
const res = {
|
||||||
return {
|
x: insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x - r,
|
||||||
x: insidePoint.x < outsidePoint.x ? insidePoint.x + r : insidePoint.x - r,
|
y: outsidePoint.y + q
|
||||||
y: insidePoint.y + q
|
|
||||||
};
|
};
|
||||||
|
logger.warn(`topp/bott calc, Q ${Q}, q ${q}, R ${R}, r ${r}`, res);
|
||||||
|
|
||||||
|
return res;
|
||||||
} else {
|
} else {
|
||||||
q = (Q * r) / R;
|
// Intersection onn sides of rect
|
||||||
r = (R * q) / Q;
|
// q = (Q * r) / R;
|
||||||
|
// q = 2;
|
||||||
|
// r = (R * q) / Q;
|
||||||
|
if (insidePoint.x < outsidePoint.x) {
|
||||||
|
r = outsidePoint.x - w - x;
|
||||||
|
} else {
|
||||||
|
// r = outsidePoint.x - w - x;
|
||||||
|
r = x - w - outsidePoint.x;
|
||||||
|
}
|
||||||
|
let q = (q = (Q * r) / R);
|
||||||
|
logger.warn(`sides calc, Q ${Q}, q ${q}, R ${R}, r ${r}`, {
|
||||||
|
x: insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x + dx - w,
|
||||||
|
y: insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x: insidePoint.x < outsidePoint.x ? insidePoint.x + r : insidePoint.x + dx - w,
|
x: insidePoint.x < outsidePoint.x ? insidePoint.x + R - r : insidePoint.x + dx - w,
|
||||||
y: insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q
|
y: insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -110,7 +153,7 @@ const intersection = (node, outsidePoint, insidePoint) => {
|
|||||||
//(edgePaths, e, edge, clusterDb, diagramtype, graph)
|
//(edgePaths, e, edge, clusterDb, diagramtype, graph)
|
||||||
export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph) {
|
export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph) {
|
||||||
let points = edge.points;
|
let points = edge.points;
|
||||||
|
let pointsHasChanged = false;
|
||||||
const tail = graph.node(e.v);
|
const tail = graph.node(e.v);
|
||||||
var head = graph.node(e.w);
|
var head = graph.node(e.w);
|
||||||
|
|
||||||
@ -147,11 +190,12 @@ export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph)
|
|||||||
}
|
}
|
||||||
lastPointOutside = point;
|
lastPointOutside = point;
|
||||||
});
|
});
|
||||||
|
pointsHasChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edge.fromCluster) {
|
if (edge.fromCluster) {
|
||||||
logger.trace('edge', edge);
|
logger.trace('edge', edge);
|
||||||
logger.trace('from cluster', clusterDb[edge.toCluster]);
|
logger.warn('from cluster', clusterDb[edge.fromCluster]);
|
||||||
const updatedPoints = [];
|
const updatedPoints = [];
|
||||||
let lastPointOutside;
|
let lastPointOutside;
|
||||||
let isInside = false;
|
let isInside = false;
|
||||||
@ -160,7 +204,7 @@ export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph)
|
|||||||
const node = clusterDb[edge.fromCluster].node;
|
const node = clusterDb[edge.fromCluster].node;
|
||||||
|
|
||||||
if (!outsideNode(node, point) && !isInside) {
|
if (!outsideNode(node, point) && !isInside) {
|
||||||
logger.trace('inside', edge.toCluster, point);
|
logger.warn('inside', edge.fromCluster, point, node);
|
||||||
|
|
||||||
// First point inside the rect
|
// First point inside the rect
|
||||||
const insterection = intersection(node, lastPointOutside, point);
|
const insterection = intersection(node, lastPointOutside, point);
|
||||||
@ -176,6 +220,7 @@ export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph)
|
|||||||
lastPointOutside = point;
|
lastPointOutside = point;
|
||||||
}
|
}
|
||||||
points = updatedPoints;
|
points = updatedPoints;
|
||||||
|
pointsHasChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The data for our line
|
// The data for our line
|
||||||
@ -275,4 +320,8 @@ export const insertEdge = function(elem, e, edge, clusterDb, diagramType, graph)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pointsHasChanged) {
|
||||||
|
return points;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
63
src/dagre-wrapper/edges.spec.js
Normal file
63
src/dagre-wrapper/edges.spec.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { intersection } from './edges';
|
||||||
|
import { setLogLevel, logger } from '../logger';
|
||||||
|
|
||||||
|
describe('Graphlib decorations', () => {
|
||||||
|
let node;
|
||||||
|
beforeEach(function () {
|
||||||
|
setLogLevel(1);
|
||||||
|
node = { x:171, y:100, width: 210, height: 184};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('intersection', function () {
|
||||||
|
it('case 1 - intersection on left edge of box', function () {
|
||||||
|
const o = {x: 31, y: 143.2257070163421};
|
||||||
|
const i = {x: 99.3359375, y: 100}
|
||||||
|
const int = intersection(node, o, i);
|
||||||
|
expect(int.x).toBe(66)
|
||||||
|
expect(int.y).toBeCloseTo(122.139)
|
||||||
|
});
|
||||||
|
|
||||||
|
it('case 2 - intersection on left edge of box', function () {
|
||||||
|
const o = {x: 310.2578125, y: 169.88002060631462};
|
||||||
|
const i = {x: 127.96875, y: 100};
|
||||||
|
const node2 = {
|
||||||
|
height: 337.5,
|
||||||
|
width: 184.4609375,
|
||||||
|
x: 100.23046875,
|
||||||
|
y: 176.75
|
||||||
|
}
|
||||||
|
const int = intersection(node2, o, i);
|
||||||
|
expect(int.x).toBeCloseTo(192.4609375)
|
||||||
|
expect(int.y).toBeCloseTo(145.15711441743503)
|
||||||
|
|
||||||
|
});
|
||||||
|
it('case 3 - intersection on otop of box outside point greater then inside point', function () {
|
||||||
|
const o = {x: 157.21875, y: 38.83361558001693};
|
||||||
|
const i = {x: 104.1328125, y: 105};
|
||||||
|
const node2 = {
|
||||||
|
width: 211.96875,
|
||||||
|
x: 113.984375,
|
||||||
|
y: 164.25,
|
||||||
|
height: 176.5
|
||||||
|
}
|
||||||
|
const int = intersection(node2, o, i);
|
||||||
|
expect(int.x).toBeCloseTo(127.39979619565217)
|
||||||
|
expect(int.y).toBeCloseTo(76)
|
||||||
|
|
||||||
|
});
|
||||||
|
it('case 4 - intersection on top of box inside point greater then inside point', function () {
|
||||||
|
const o = {x: 144.65625, y: 38.83361558001693};
|
||||||
|
const i = {x: 197.7421875, y: 105};
|
||||||
|
const node2 = {
|
||||||
|
width: 211.96875,
|
||||||
|
x: 113.984375,
|
||||||
|
y: 164.25,
|
||||||
|
height: 176.5
|
||||||
|
}
|
||||||
|
const int = intersection(node2, o, i);
|
||||||
|
expect(int.x).toBeCloseTo(167.9232336956522)
|
||||||
|
expect(int.y).toBeCloseTo(76)
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -124,8 +124,8 @@ const recursiveRender = (_elem, graph, diagramtype, parentCluster) => {
|
|||||||
const edge = graph.edge(e);
|
const edge = graph.edge(e);
|
||||||
log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge);
|
log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge);
|
||||||
|
|
||||||
insertEdge(edgePaths, e, edge, clusterDb, diagramtype, graph);
|
const updatedPath = insertEdge(edgePaths, e, edge, clusterDb, diagramtype, graph);
|
||||||
positionEdgeLabel(edge);
|
positionEdgeLabel(edge, updatedPath);
|
||||||
});
|
});
|
||||||
|
|
||||||
return elem;
|
return elem;
|
||||||
|
@ -171,7 +171,9 @@ export const validate = graph => {
|
|||||||
export const findNonClusterChild = (id, graph) => {
|
export const findNonClusterChild = (id, graph) => {
|
||||||
// const node = graph.node(id);
|
// const node = graph.node(id);
|
||||||
log.trace('Searching', id);
|
log.trace('Searching', id);
|
||||||
const children = graph.children(id);
|
// const children = graph.children(id).reverse();
|
||||||
|
const children = graph.children(id); //.reverse();
|
||||||
|
log.trace('Searching children of id ', id, children);
|
||||||
if (children.length < 1) {
|
if (children.length < 1) {
|
||||||
log.trace('This is a valid node', id);
|
log.trace('This is a valid node', id);
|
||||||
return id;
|
return id;
|
||||||
@ -213,7 +215,7 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
|||||||
graph.nodes().forEach(function(id) {
|
graph.nodes().forEach(function(id) {
|
||||||
const children = graph.children(id);
|
const children = graph.children(id);
|
||||||
if (children.length > 0) {
|
if (children.length > 0) {
|
||||||
log.trace(
|
log.warn(
|
||||||
'Cluster identified',
|
'Cluster identified',
|
||||||
id,
|
id,
|
||||||
' Replacement id in edges: ',
|
' Replacement id in edges: ',
|
||||||
@ -266,17 +268,17 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
|||||||
// Check if link is either from or to a cluster
|
// Check if link is either from or to a cluster
|
||||||
log.trace('Fix', clusterDb, 'ids:', e.v, e.w, 'Translateing: ', clusterDb[e.v], clusterDb[e.w]);
|
log.trace('Fix', clusterDb, 'ids:', e.v, e.w, 'Translateing: ', clusterDb[e.v], clusterDb[e.w]);
|
||||||
if (clusterDb[e.v] || clusterDb[e.w]) {
|
if (clusterDb[e.v] || clusterDb[e.w]) {
|
||||||
log.trace('Fixing and trixing - removing', e.v, e.w, e.name);
|
log.warn('Fixing and trixing - removing', e.v, e.w, e.name);
|
||||||
v = getAnchorId(e.v);
|
v = getAnchorId(e.v);
|
||||||
w = getAnchorId(e.w);
|
w = getAnchorId(e.w);
|
||||||
graph.removeEdge(e.v, e.w, e.name);
|
graph.removeEdge(e.v, e.w, e.name);
|
||||||
if (v !== e.v) edge.fromCluster = e.v;
|
if (v !== e.v) edge.fromCluster = e.v;
|
||||||
if (w !== e.w) edge.toCluster = e.w;
|
if (w !== e.w) edge.toCluster = e.w;
|
||||||
log.trace('Replacing with', v, w, e.name);
|
log.warn('Replacing with', v, w, e.name);
|
||||||
graph.setEdge(v, w, edge, e.name);
|
graph.setEdge(v, w, edge, e.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
log.debug('Adjusted Graph', graphlib.json.write(graph));
|
log.warn('Adjusted Graph', graphlib.json.write(graph));
|
||||||
|
|
||||||
log.trace(clusterDb);
|
log.trace(clusterDb);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user