Layout algorithm in place

This commit is contained in:
Knut Sveidqvist
2022-07-24 11:05:54 +02:00
parent 7de68f0bf2
commit 8e5e212c49
8 changed files with 271 additions and 32 deletions

View File

@@ -2,7 +2,9 @@
import { select } from 'd3';
import { log, getConfig, setupGraphViewbox } from '../../diagram-api/diagramAPI';
import svgDraw from './svgDraw';
import { BoundingBox, Layout, Tree } from 'non-layered-tidy-tree-layout';
import clone from 'fast-clone';
import db from './mindmapDb';
/**
* @param {any} svg The svg element to draw the diagram onto
* @param {object} mindmap The maindmap data and hierarchy
@@ -17,17 +19,181 @@ function drawNodes(svg, mindmap, conf) {
}
}
/** @param {any} svg The svg element to draw the diagram onto */
function drawEdges() {}
/**
* @param mindmap
* @param callback
*/
function eachNode(mindmap, callback) {
callback(mindmap);
if (mindmap.children) {
mindmap.children.forEach((child) => {
eachNode(child, callback);
});
}
}
/** @param {object} mindmap */
function transpose(mindmap) {
console.log('transpose', mindmap);
eachNode(mindmap, (node) => {
// node.y = node.y - (node.y - bb.top) * 2 - node.height;
const orgWidth = node.width;
const orgX = node.x;
node.width = node.height;
node.height = orgWidth;
node.x = node.y;
node.y = orgX;
});
return mindmap;
}
/** @param {object} mindmap */
function bottomToUp(mindmap) {
console.log('bottomToUp', mindmap);
eachNode(mindmap.result, (node) => {
// node.y = node.y - (node.y - bb.top) * 2 - node.height;
node.y = node.y - (node.y - 0) * 2 - node.height;
});
return mindmap;
}
/** @param {object} mindmap The mindmap hierarchy */
function rightToLeft(mindmap) {
console.log('bottomToUp', mindmap);
eachNode(mindmap.result, (node) => {
// node.y = node.y - (node.y - bb.top) * 2 - node.height;
node.x = node.x - (node.x - 0) * 2 - node.width;
});
return mindmap;
}
/**
* @param mindmap
* @param dir
* @param conf
*/
function layout(mindmap, dir, conf) {
const bb = new BoundingBox(40, 40);
const layout = new Layout(bb);
switch (dir) {
case 'TB':
return layout.layout(mindmap);
case 'BT':
return bottomToUp(layout.layout(mindmap));
case 'RL': {
transpose(mindmap);
let newRes = layout.layout(mindmap);
transpose(newRes.result);
return rightToLeft(newRes);
}
case 'LR': {
transpose(mindmap);
let newRes = layout.layout(mindmap);
transpose(newRes.result);
return newRes;
}
default:
}
}
const dirFromIndex = (index) => {
const dirNum = index % 4;
switch (dirNum) {
case 0:
return 'LR';
case 1:
return 'RL';
case 2:
return 'TB';
case 3:
return 'BT';
default:
return 'TB';
}
};
const mergeTrees = (node, trees) => {
node.x = trees[0].result.x;
node.y = trees[0].result.y;
trees.forEach((tree) => {
tree.result.children.forEach((child) => {
const dx = node.x - tree.result.x;
const dy = node.y - tree.result.y;
eachNode(child, (childNode) => {
const orgNode = db.getNodeById(childNode.id);
if (orgNode) {
orgNode.x = childNode.x + dx;
orgNode.y = childNode.y + dy;
}
});
});
});
return node;
};
/**
* @param node
* @param isRoot
* @param parent
* @param conf
*/
function layoutMindmap(node, isRoot) {}
function layoutMindmap(node, conf) {
// BoundingBox(gap, bottomPadding)
// const bb = new BoundingBox(10, 10);
// const layout = new Layout(bb);
// // const layout = new HorizontalLayout(bb);
const trees = [];
// node.children.forEach((child, index) => {
// const tree = clone(node);
// tree.children = [tree.children[index]];
// trees.push(layout(tree, dirFromIndex(index), conf));
// });
let cnt = 0;
// For each direction, create a new tree with the same root, and add a ubset of the children to it.
for (let i = 0; i < 4; i++) {
// Calculate the number of the children of the root node that will be used in this direction
const numChildren =
Math.floor(node.children.length / 4) + (node.children.length % 4 > i ? 1 : 0);
// Copy the original root node
const tree = clone(node);
// Setup the new copy with the children to be rendered in this direction
tree.children = [];
for (let j = 0; j < numChildren; j++) {
tree.children.push(node.children[cnt]);
cnt++;
}
if (tree.children.length > 0) {
trees.push(layout(tree, dirFromIndex(i), conf));
}
}
// Merge the trees into a single tree
const result = mergeTrees(node, trees);
// return layout(node, 'BT', conf);
// const res = layout(node, 'BT', conf);
// res.result.children = [];
// trees.forEach((tree) => {
// res.result.children.push(tree.result);
// });
console.log('Trees', trees);
return node;
}
/**
* @param node
* @param isRoot
* @param conf
*/
function positionNodes(node, isRoot) {}
function positionNodes(node, conf) {
svgDraw.positionNode(node, conf);
if (node.children) {
node.children.forEach((child) => {
positionNodes(child, conf);
});
}
}
/**
* Draws a an info picture in the tag with id: id based on the graph definition in text.
@@ -63,16 +229,6 @@ export const draw = (text, id, version, diagObj) => {
const g = svg.append('g');
const mm = diagObj.db.getMindmap();
// mm.x = 0;
// mm.y = 0;
// svgDraw.drawNode(g, mm, getConfig());
// mm.children.forEach((child) => {
// child.x = 200;
// child.y = 200;
// child.width = 200;
// svgDraw.drawNode(g, child, getConfig());
// });
// Draw the graph and start with drawing the nodes without proper position
// this gives us the size of the nodes and we can set the positions later
@@ -82,12 +238,14 @@ export const draw = (text, id, version, diagObj) => {
// Next step is to layout the mindmap, giving each node a position
// layoutMindmap(mm, conf);
console.log('Before', mm);
const positionedMindmap = layoutMindmap(mm, conf);
console.log(positionedMindmap);
// After this we can draw, first the edges and the then nodes with the correct position
// drawEdges(svg, mm, conf);
// positionNodes(svg, mm, conf);
positionNodes(positionedMindmap, conf);
// Setup the view box and size of the svg element
setupGraphViewbox(undefined, svg, conf.mindmap.diagramPadding, conf.mindmap.useMaxWidth);