mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-15 14:29:25 +02:00
5237 Better algorithm to pich replacement node when faking position for subgraphs
This commit is contained in:
@@ -77,19 +77,58 @@
|
|||||||
<body>
|
<body>
|
||||||
<pre id="diagram" class="mermaid">
|
<pre id="diagram" class="mermaid">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
subgraph Apa["Apa"]
|
subgraph Apa["Apa"]
|
||||||
A["Start"]
|
A["Start"]
|
||||||
B["This is B"]
|
B["This is B"]
|
||||||
|
end
|
||||||
|
A --> B & C["C"]
|
||||||
|
Apa --> C
|
||||||
|
</pre
|
||||||
|
>
|
||||||
|
<pre id="diagram" class="mermaid">
|
||||||
|
flowchart LR
|
||||||
|
subgraph Apa["Apa"]
|
||||||
|
B["This is B"]
|
||||||
|
A["Start"]
|
||||||
|
end
|
||||||
|
A --> B & C["C"]
|
||||||
|
Apa --> C
|
||||||
|
</pre
|
||||||
|
>
|
||||||
|
<pre id="diagram" class="mermaid">
|
||||||
|
flowchart LR
|
||||||
|
subgraph Apa["Apa"]
|
||||||
|
subgraph Gorilla
|
||||||
|
A["Start"]
|
||||||
|
B["This is B"]
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
A --> B & C["C"]
|
||||||
|
Gorilla --> C
|
||||||
|
</pre
|
||||||
|
>
|
||||||
|
<pre id="diagram" class="mermaid">
|
||||||
|
flowchart LR
|
||||||
|
subgraph Apa["Apa"]
|
||||||
|
subgraph Gorilla
|
||||||
|
A["Start"]
|
||||||
|
B["This is B"]
|
||||||
|
end
|
||||||
|
end
|
||||||
A --> B & C["C"]
|
A --> B & C["C"]
|
||||||
Apa --> C
|
Apa --> C
|
||||||
</pre
|
</pre
|
||||||
>
|
>
|
||||||
<pre id="diagram" class="mermaid2">
|
<pre id="diagram" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
subgraph Apa["Apa"]
|
subgraph Apa["Apa"]
|
||||||
B --> B & C
|
subgraph Gorilla
|
||||||
|
B["This is B"]
|
||||||
|
A["Start"]
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
Apa --> C
|
||||||
|
A --> B & C["C"]
|
||||||
</pre
|
</pre
|
||||||
>
|
>
|
||||||
<pre id="diagram" class="mermaid2">
|
<pre id="diagram" class="mermaid2">
|
||||||
|
@@ -8,6 +8,7 @@ export const findCommonAncestor = (id1: string, id2: string, treeData: TreeData)
|
|||||||
const visited = new Set();
|
const visited = new Set();
|
||||||
let currentId = id1;
|
let currentId = id1;
|
||||||
|
|
||||||
|
// Edge case with self edges
|
||||||
if (id1 === id2) {
|
if (id1 === id2) {
|
||||||
return parentById[id1] || 'root';
|
return parentById[id1] || 'root';
|
||||||
}
|
}
|
||||||
|
@@ -152,27 +152,58 @@ export const validate = (graph) => {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const findCommonEdges = (graph, id1, id2) => {
|
||||||
|
const edges1 = graph.edges().filter((edge) => edge.v === id1 || edge.w === id1);
|
||||||
|
const edges2 = graph.edges().filter((edge) => edge.v === id2 || edge.w === id2);
|
||||||
|
const edges1Prim = edges1.map((edge) => {
|
||||||
|
return { v: edge.v === id1 ? id2 : edge.v, w: edge.w === id1 ? id1 : edge.w };
|
||||||
|
});
|
||||||
|
const edges2Prim = edges2.map((edge) => {
|
||||||
|
return { v: edge.v, w: edge.w };
|
||||||
|
});
|
||||||
|
const result = edges1Prim.filter((edgeIn1) => {
|
||||||
|
return edges2Prim.filter((edge) => edgeIn1.v === edge.v && edgeIn1.w === edge.w).length > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds a child that is not a cluster. When faking an edge between a node and a cluster.
|
* Finds a child that is not a cluster. When faking an edge between a node and a cluster.
|
||||||
*
|
*
|
||||||
* @param id
|
* @param id
|
||||||
* @param {any} graph
|
* @param {any} graph
|
||||||
*/
|
*/
|
||||||
export const findNonClusterChild = (id, graph) => {
|
export const findNonClusterChild = (id, graph, clusterId) => {
|
||||||
log.trace('Searching', id);
|
const children = graph.children(id);
|
||||||
const children = graph.children(id).reverse();
|
|
||||||
log.trace('Searching children of id ', id, children);
|
log.trace('Searching children of id ', id, children);
|
||||||
if (children.length < 1) {
|
if (children.length < 1) {
|
||||||
log.trace('This is a valid node', id);
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
let reserve;
|
||||||
for (const child of children) {
|
for (const child of children) {
|
||||||
const _id = findNonClusterChild(child, graph);
|
const _id = findNonClusterChild(child, graph, clusterId);
|
||||||
|
|
||||||
|
// Edge chase where the cluster has an edge to a node and the selected
|
||||||
|
// child has a link to the same node
|
||||||
|
const commonEdges = findCommonEdges(graph, clusterId, _id);
|
||||||
|
|
||||||
if (_id) {
|
if (_id) {
|
||||||
log.trace('Found replacement for', id, ' => ', _id);
|
if (commonEdges.length > 0) {
|
||||||
return _id;
|
// console.log(
|
||||||
|
// '\x1B[44;93;4m abc24 The replacement also has an edge',
|
||||||
|
// clusterId,
|
||||||
|
// ' => ',
|
||||||
|
// _id,
|
||||||
|
// graph.edges()
|
||||||
|
// );
|
||||||
|
reserve = _id;
|
||||||
|
} else {
|
||||||
|
return _id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return reserve;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAnchorId = (id) => {
|
const getAnchorId = (id) => {
|
||||||
@@ -207,10 +238,10 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
|||||||
'Cluster identified',
|
'Cluster identified',
|
||||||
id,
|
id,
|
||||||
' Replacement id in edges: ',
|
' Replacement id in edges: ',
|
||||||
findNonClusterChild(id, graph)
|
findNonClusterChild(id, graph, id)
|
||||||
);
|
);
|
||||||
descendants[id] = extractDescendants(id, graph);
|
descendants[id] = extractDescendants(id, graph);
|
||||||
clusterDb[id] = { id: findNonClusterChild(id, graph), clusterData: graph.node(id) };
|
clusterDb[id] = { id: findNonClusterChild(id, graph, id), clusterData: graph.node(id) };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user