mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-02-04 07:13:25 +08:00
#2028 Updated layout algorithm
This commit is contained in:
parent
fe3e471880
commit
ddc006e49b
@ -57,7 +57,7 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<pre style="background:black;color:white">
|
||||
<pre style="background: black; color: white">
|
||||
swimlane LR
|
||||
subgraph "`one`"
|
||||
start -- l1 --> cat --> rat
|
||||
@ -71,7 +71,8 @@
|
||||
end
|
||||
cat --> monkey
|
||||
cow --> dog
|
||||
</pre>
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram" class="mermaid">
|
||||
swimlane LR
|
||||
subgraph "`one`"
|
||||
@ -80,16 +81,31 @@ swimlane LR
|
||||
subgraph "`two`"
|
||||
monkey -- l2 --> dog --> done2
|
||||
end
|
||||
subgraph "`three`"
|
||||
subgraph "`three`"
|
||||
cow --> horse --> done3
|
||||
cow --> sheep --> done3
|
||||
end
|
||||
subgraph "`four`"
|
||||
panda -->
|
||||
kangaroo --> done4
|
||||
end
|
||||
cat --> monkey
|
||||
cow --> dog
|
||||
kangaroo --> sheep
|
||||
</pre>
|
||||
|
||||
|
||||
monkey dog --> cat monkey --> cow -->
|
||||
<pre id="diagram" class="mermaid2">
|
||||
swimlane LR
|
||||
subgraph "`three`"
|
||||
bat --> cow
|
||||
cow --> sheep
|
||||
end
|
||||
subgraph "`four`"
|
||||
panda -->
|
||||
kangaroo --> done4
|
||||
end
|
||||
kangaroo --> sheep
|
||||
</pre>
|
||||
<!-- <div id="cy"></div> -->
|
||||
<!-- <script src="http://localhost:9000/packages/mermaid-mindmap/dist/mermaid-mindmap-detector.js"></script> -->
|
||||
<!-- <script src="./mermaid-example-diagram-detector.js"></script> -->
|
||||
|
@ -28,6 +28,11 @@ export function assignRanks(graph, subgraphLookupTable) {
|
||||
let cnt = 0;
|
||||
let changesDetected = true;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param nodeId
|
||||
* @param currentRank
|
||||
*/
|
||||
function dfs(nodeId, currentRank) {
|
||||
if (visited.has(nodeId)) {
|
||||
return;
|
||||
@ -36,7 +41,7 @@ export function assignRanks(graph, subgraphLookupTable) {
|
||||
visited.add(nodeId);
|
||||
const existingRank = ranks.get(nodeId) || 0;
|
||||
|
||||
console.log('APA444 DFS Base case for', nodeId, 'to', Math.max(existingRank, currentRank));
|
||||
// console.log('APA444 DFS Base case for', nodeId, 'to', Math.max(existingRank, currentRank));
|
||||
if (lock.get(nodeId) !== 1) {
|
||||
ranks.set(nodeId, Math.max(existingRank, currentRank));
|
||||
} else {
|
||||
@ -61,42 +66,52 @@ export function assignRanks(graph, subgraphLookupTable) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function adjustSuccessors() {
|
||||
console.log('APA444 Adjusting successors');
|
||||
graph.nodes().forEach((nodeId) => {
|
||||
if (graph.predecessors(nodeId).length === 0) {
|
||||
graph.successors(nodeId).forEach((successorNodeId) => {
|
||||
if (subgraphLookupTable[successorNodeId] !== subgraphLookupTable[nodeId]) {
|
||||
const newRank = ranks.get(successorNodeId);
|
||||
ranks.set(nodeId, newRank);
|
||||
console.log('APA444 POST-process case for', nodeId, 'to', newRank);
|
||||
lock.set(nodeId, 1);
|
||||
changesDetected = true;
|
||||
// setRankFromTopNodes();
|
||||
console.log('APA444 Going through nodes', nodeId);
|
||||
// if (graph.predecessors(nodeId).length === 0) {
|
||||
console.log('APA444 has no predecessors', nodeId);
|
||||
graph.successors(nodeId).forEach((successorNodeId) => {
|
||||
console.log('APA444 has checking successor', successorNodeId);
|
||||
if (subgraphLookupTable[successorNodeId] !== subgraphLookupTable[nodeId]) {
|
||||
const newRank = ranks.get(successorNodeId);
|
||||
ranks.set(nodeId, newRank);
|
||||
console.log('APA444 POST-process case for', nodeId, 'to', newRank);
|
||||
lock.set(nodeId, 1);
|
||||
changesDetected = true;
|
||||
// setRankFromTopNodes();
|
||||
|
||||
// Adjust ranks of successors in the same subgraph
|
||||
graph.successors(nodeId).forEach((sameSubGraphSuccessorNodeId) => {
|
||||
if (
|
||||
subgraphLookupTable[sameSubGraphSuccessorNodeId] === subgraphLookupTable[nodeId]
|
||||
) {
|
||||
console.log(
|
||||
'APA444 Adjusting rank of',
|
||||
sameSubGraphSuccessorNodeId,
|
||||
'to',
|
||||
newRank + 1
|
||||
);
|
||||
ranks.set(sameSubGraphSuccessorNodeId, newRank + 1);
|
||||
lock.set(sameSubGraphSuccessorNodeId, 1);
|
||||
changesDetected = true;
|
||||
// dfs(sameSubGraphSuccessorNodeId, newRank + 1);
|
||||
// setRankFromTopNodes();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// Adjust ranks of successors in the same subgraph
|
||||
graph.successors(nodeId).forEach((sameSubGraphSuccessorNodeId) => {
|
||||
if (subgraphLookupTable[sameSubGraphSuccessorNodeId] === subgraphLookupTable[nodeId]) {
|
||||
console.log(
|
||||
'APA444 Adjusting rank of',
|
||||
sameSubGraphSuccessorNodeId,
|
||||
'to',
|
||||
newRank + 1
|
||||
);
|
||||
ranks.set(sameSubGraphSuccessorNodeId, newRank + 1);
|
||||
lock.set(sameSubGraphSuccessorNodeId, 1);
|
||||
changesDetected = true;
|
||||
// dfs(sameSubGraphSuccessorNodeId, newRank + 1);
|
||||
// setRankFromTopNodes();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('APA444 Node', nodeId, ' and ', successorNodeId, ' is in the same lane');
|
||||
}
|
||||
});
|
||||
// }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function setRankFromTopNodes() {
|
||||
visited = new Set();
|
||||
graph.nodes().forEach((nodeId) => {
|
||||
@ -120,6 +135,7 @@ export function assignRanks(graph, subgraphLookupTable) {
|
||||
*
|
||||
* @param graph
|
||||
* @param subgraphLÖookupTable
|
||||
* @param ranks
|
||||
* @param subgraphLookupTable
|
||||
*/
|
||||
export function assignAffinities(graph, ranks, subgraphLookupTable) {
|
||||
@ -130,27 +146,27 @@ export function assignAffinities(graph, ranks, subgraphLookupTable) {
|
||||
graph.nodes().forEach((nodeId) => {
|
||||
const swimlane = subgraphLookupTable[nodeId];
|
||||
const rank = ranks.get(nodeId);
|
||||
const key = swimlane+':'+rank;
|
||||
const key = swimlane + ':' + rank;
|
||||
let currentAffinity = swimlaneRankAffinities.get(key);
|
||||
if(typeof currentAffinity === 'undefined'){
|
||||
if (currentAffinity === undefined) {
|
||||
currentAffinity = -1;
|
||||
}
|
||||
const newAffinity = currentAffinity + 1;
|
||||
swimlaneRankAffinities.set(key, newAffinity);
|
||||
affinities.set(nodeId, newAffinity);
|
||||
let currentMaxAffinity = swimlaneMaxAffinity.get(swimlane);
|
||||
if(typeof currentMaxAffinity === 'undefined'){
|
||||
if (currentMaxAffinity === undefined) {
|
||||
swimlaneMaxAffinity.set(swimlane, 0);
|
||||
currentMaxAffinity = 0;
|
||||
}
|
||||
if(newAffinity > currentMaxAffinity){
|
||||
if (newAffinity > currentMaxAffinity) {
|
||||
swimlaneMaxAffinity.set(swimlane, newAffinity);
|
||||
}
|
||||
});
|
||||
|
||||
// console.log('APA444 affinities', swimlaneRankAffinities);
|
||||
|
||||
return {affinities, swimlaneMaxAffinity};
|
||||
return { affinities, swimlaneMaxAffinity };
|
||||
//return affinities;
|
||||
}
|
||||
|
||||
@ -163,20 +179,19 @@ export function swimlaneLayout(graph, diagObj) {
|
||||
const subgraphLookupTable = getSubgraphLookupTable(diagObj);
|
||||
const ranks = assignRanks(graph, subgraphLookupTable);
|
||||
|
||||
const {affinities, swimlaneMaxAffinity} = assignAffinities(graph, ranks, subgraphLookupTable);
|
||||
const { affinities, swimlaneMaxAffinity } = assignAffinities(graph, ranks, subgraphLookupTable);
|
||||
// const affinities = assignAffinities(graph, ranks, subgraphLookupTable);
|
||||
|
||||
const subGraphs = diagObj.db.getSubGraphs();
|
||||
const lanes = [];
|
||||
const laneDb = {};
|
||||
let xPos = 0;
|
||||
for (let i = 0; i < subGraphs.length; i++) {
|
||||
const subG = subGraphs[i];
|
||||
for (const subG of subGraphs) {
|
||||
const maxAffinity = swimlaneMaxAffinity.get(subG.id);
|
||||
const lane = {
|
||||
title: subG.title,
|
||||
x: xPos,
|
||||
width: 200 + maxAffinity*150,
|
||||
width: 200 + maxAffinity * 150,
|
||||
};
|
||||
xPos += lane.width;
|
||||
lanes.push(lane);
|
||||
@ -187,6 +202,7 @@ export function swimlaneLayout(graph, diagObj) {
|
||||
// Basic layout, calculate the node positions based on rank
|
||||
graph.nodes().forEach((nodeId) => {
|
||||
const rank = ranks.get(nodeId);
|
||||
|
||||
if (!rankWidth[rank]) {
|
||||
const laneId = subgraphLookupTable[nodeId];
|
||||
const lane = laneDb[laneId];
|
||||
@ -195,7 +211,7 @@ export function swimlaneLayout(graph, diagObj) {
|
||||
const affinity = affinities.get(nodeId);
|
||||
|
||||
console.log('APA444', nodeId, 'rank', rank, 'affinity', affinity);
|
||||
graph.setNode(nodeId, { y: rank * 200 + 50, x: lane.x + 150*affinity + lane.width / 2 });
|
||||
graph.setNode(nodeId, { y: rank * 200 + 50, x: lane.x + 150 * affinity + 100 });
|
||||
// lane.width = Math.max(lane.width, lane.x + 150*affinity + lane.width / 4);
|
||||
}
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user