DuyTa's picture
Upload folder using huggingface_hub
bc20498 verified
raw
history blame
3.41 kB
import { layout, Tree } from './algorithm'
class BoundingBox {
/**
* @param {number} gap - the gap between sibling nodes
* @param {number} bottomPadding - the height reserved for connection drawing
*/
constructor(gap, bottomPadding) {
this.gap = gap
this.bottomPadding = bottomPadding
}
addBoundingBox(width, height) {
return { width: width + this.gap, height: height + this.bottomPadding }
}
/**
* Return the coordinate without the bounding box for a node
*/
removeBoundingBox(x, y) {
return { x: x + this.gap / 2, y }
}
}
class Layout {
constructor(boundingBox) {
this.bb = boundingBox
}
/**
* Layout treeData.
* Return modified treeData and the bounding box encompassing all the nodes.
*
* See getSize() for more explanation.
*/
layout(treeData) {
const tree = this.convert(treeData)
layout(tree)
const { boundingBox, result } = this.assignLayout(tree, treeData)
return { result, boundingBox }
}
/**
* Returns Tree to layout, with bounding boxes added to each node.
*/
convert(treeData, y = 0) {
if (treeData === null) return null
const { width, height } = this.bb.addBoundingBox(
treeData.width,
treeData.height
)
let children = []
if (treeData.children && treeData.children.length) {
for (let i = 0; i < treeData.children.length; i++) {
children[i] = this.convert(treeData.children[i], y + height)
}
}
return new Tree(width, height, y, children)
}
/**
* Assign layout tree x, y coordinates back to treeData,
* with bounding boxes removed.
*/
assignCoordinates(tree, treeData) {
const { x, y } = this.bb.removeBoundingBox(tree.x, tree.y)
treeData.x = x
treeData.y = y
for (let i = 0; i < tree.c.length; i++) {
this.assignCoordinates(tree.c[i], treeData.children[i])
}
}
/**
* Return the bounding box that encompasses all the nodes.
* The result has a structure of
* { left: number, right: number, top: number, bottom: nubmer}.
* This is not the same bounding box concept as the `BoundingBox` class
* used to construct `Layout` class.
*/
getSize(treeData, box = null) {
const { x, y, width, height } = treeData
if (box === null) {
box = { left: x, right: x + width, top: y, bottom: y + height }
}
box.left = Math.min(box.left, x)
box.right = Math.max(box.right, x + width)
box.top = Math.min(box.top, y)
box.bottom = Math.max(box.bottom, y + height)
if (treeData.children) {
for (const child of treeData.children) {
this.getSize(child, box)
}
}
return box
}
/**
* This function does assignCoordinates and getSize in one pass.
*/
assignLayout(tree, treeData, box = null) {
const { x, y } = this.bb.removeBoundingBox(tree.x, tree.y)
treeData.x = x
treeData.y = y
const { width, height } = treeData
if (box === null) {
box = { left: x, right: x + width, top: y, bottom: y + height }
}
box.left = Math.min(box.left, x)
box.right = Math.max(box.right, x + width)
box.top = Math.min(box.top, y)
box.bottom = Math.max(box.bottom, y + height)
for (let i = 0; i < tree.c.length; i++) {
this.assignLayout(tree.c[i], treeData.children[i], box)
}
return { result: treeData, boundingBox: box }
}
}
export { Layout, BoundingBox }