2024-01-18 17:07:34 +01:00
|
|
|
import type { BlockDB } from './blockDB.js';
|
2023-09-05 11:13:27 +02:00
|
|
|
import type { Block } from './blockTypes.js';
|
2023-10-15 22:21:25 +02:00
|
|
|
import { log } from '../../logger.js';
|
|
|
|
const padding = 8;
|
2023-09-05 11:13:27 +02:00
|
|
|
|
2023-10-15 22:21:25 +02:00
|
|
|
interface BlockPosition {
|
|
|
|
px: number;
|
|
|
|
py: number;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function calculateBlockPosition(columns: number, position: number): BlockPosition {
|
2024-01-18 14:28:14 +01:00
|
|
|
// log.debug('calculateBlockPosition abc89', columns, position);
|
2023-10-15 22:21:25 +02:00
|
|
|
// Ensure that columns is a positive integer
|
|
|
|
if (columns === 0 || !Number.isInteger(columns)) {
|
|
|
|
throw new Error('Columns must be an integer !== 0.');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that position is a non-negative integer
|
|
|
|
if (position < 0 || !Number.isInteger(position)) {
|
2024-01-08 15:48:59 +01:00
|
|
|
throw new Error('Position must be a non-negative integer.' + position);
|
2023-10-15 22:21:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (columns < 0) {
|
|
|
|
// Auto coulumns is set
|
|
|
|
return { px: position, py: 0 };
|
|
|
|
}
|
|
|
|
if (columns === 1) {
|
|
|
|
// Auto coulumns is set
|
|
|
|
return { px: 0, py: position };
|
|
|
|
}
|
|
|
|
// Calculate posX and posY
|
|
|
|
const px = position % columns;
|
|
|
|
const py = Math.floor(position / columns);
|
2024-01-18 14:28:14 +01:00
|
|
|
// log.debug('calculateBlockPosition abc89', columns, position, '=> (', px, py, ')');
|
2023-10-15 22:21:25 +02:00
|
|
|
return { px, py };
|
|
|
|
}
|
2023-10-03 20:12:33 +02:00
|
|
|
|
2024-01-08 14:03:42 +01:00
|
|
|
const getMaxChildSize = (block: Block) => {
|
|
|
|
let maxWidth = 0;
|
|
|
|
let maxHeight = 0;
|
|
|
|
// find max width of children
|
2024-01-18 14:28:14 +01:00
|
|
|
// log.debug('getMaxChildSize abc95 (start) parent:', block.id);
|
2024-01-08 14:03:42 +01:00
|
|
|
for (const child of block.children) {
|
|
|
|
const { width, height, x, y } = child.size || { width: 0, height: 0, x: 0, y: 0 };
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug(
|
2024-01-18 10:22:09 +01:00
|
|
|
'getMaxChildSize abc95 child:',
|
|
|
|
child.id,
|
|
|
|
'width:',
|
|
|
|
width,
|
|
|
|
'height:',
|
|
|
|
height,
|
|
|
|
'x:',
|
|
|
|
x,
|
|
|
|
'y:',
|
2024-01-18 14:28:14 +01:00
|
|
|
y,
|
|
|
|
child.type
|
2024-01-18 10:22:09 +01:00
|
|
|
);
|
2024-01-18 14:28:14 +01:00
|
|
|
if (child.type === 'space') {
|
|
|
|
continue;
|
|
|
|
}
|
2024-01-08 14:03:42 +01:00
|
|
|
if (width > maxWidth) {
|
2024-01-18 10:22:09 +01:00
|
|
|
maxWidth = width / (block.w || 1);
|
2024-01-08 14:03:42 +01:00
|
|
|
}
|
|
|
|
if (height > maxHeight) {
|
|
|
|
maxHeight = height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return { width: maxWidth, height: maxHeight };
|
|
|
|
};
|
|
|
|
|
2024-01-18 15:44:16 +01:00
|
|
|
function setBlockSizes(block: Block, db: BlockDB, sieblingWidth = 0, sieblingHeight = 0) {
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug(
|
2024-01-18 10:22:09 +01:00
|
|
|
'setBlockSizes abc95 (start)',
|
|
|
|
block.id,
|
|
|
|
block?.size?.x,
|
|
|
|
'block width =',
|
2024-01-18 14:28:14 +01:00
|
|
|
block?.size,
|
2024-01-18 10:22:09 +01:00
|
|
|
'sieblingWidth',
|
|
|
|
sieblingWidth
|
|
|
|
);
|
2024-01-18 14:28:14 +01:00
|
|
|
if (!block?.size?.width) {
|
|
|
|
block.size = {
|
|
|
|
width: sieblingWidth,
|
|
|
|
height: sieblingHeight,
|
|
|
|
x: 0,
|
|
|
|
y: 0,
|
|
|
|
};
|
|
|
|
}
|
2023-10-03 14:19:08 +02:00
|
|
|
const totalWidth = 0;
|
|
|
|
const totalHeight = 0;
|
|
|
|
let maxWidth = 0;
|
|
|
|
let maxHeight = 0;
|
|
|
|
|
2024-01-08 14:03:42 +01:00
|
|
|
if (block.children?.length > 0) {
|
2023-09-05 11:13:27 +02:00
|
|
|
for (const child of block.children) {
|
2024-01-08 14:03:42 +01:00
|
|
|
setBlockSizes(child, db);
|
2023-09-05 11:13:27 +02:00
|
|
|
}
|
|
|
|
// find max width of children
|
2024-01-08 14:03:42 +01:00
|
|
|
const childSize = getMaxChildSize(block);
|
|
|
|
maxWidth = childSize.width;
|
|
|
|
maxHeight = childSize.height;
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug('setBlockSizes abc95 maxWidth of', block.id, ':s children is ', maxWidth, maxHeight);
|
2023-09-05 11:13:27 +02:00
|
|
|
|
|
|
|
// set width of block to max width of children
|
|
|
|
for (const child of block.children) {
|
|
|
|
if (child.size) {
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug(
|
|
|
|
'abc95 Setting size of children of',
|
|
|
|
block.id,
|
|
|
|
'id=',
|
|
|
|
child.id,
|
|
|
|
maxWidth,
|
|
|
|
maxHeight,
|
|
|
|
child.size
|
|
|
|
);
|
2024-01-18 15:44:16 +01:00
|
|
|
child.size.width = maxWidth * (child.w || 1) + padding * ((child.w || 1) - 1);
|
2023-09-05 11:13:27 +02:00
|
|
|
child.size.height = maxHeight;
|
2023-10-03 20:12:33 +02:00
|
|
|
child.size.x = 0;
|
|
|
|
child.size.y = 0;
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug(
|
2024-01-18 10:22:09 +01:00
|
|
|
'abc95 updating size of ',
|
|
|
|
block.id,
|
|
|
|
' children child:',
|
|
|
|
child.id,
|
|
|
|
'maxWidth:',
|
|
|
|
maxWidth,
|
|
|
|
'maxHeight:',
|
|
|
|
maxHeight
|
|
|
|
);
|
2023-09-05 11:13:27 +02:00
|
|
|
}
|
|
|
|
}
|
2024-01-08 14:03:42 +01:00
|
|
|
for (const child of block.children) {
|
2024-01-18 14:28:14 +01:00
|
|
|
// log.debug('abc95 fin 2 Setting size', child.id, maxWidth, maxHeight, child.size);
|
2024-01-08 15:48:59 +01:00
|
|
|
setBlockSizes(child, db, maxWidth, maxHeight);
|
2024-01-18 14:28:14 +01:00
|
|
|
// log.debug('abc95 fin 3 Setting size', child.id, maxWidth, maxHeight, child.size);
|
2024-01-08 14:03:42 +01:00
|
|
|
}
|
2023-09-05 11:13:27 +02:00
|
|
|
|
2023-10-15 22:21:25 +02:00
|
|
|
const columns = block.columns || -1;
|
|
|
|
const numItems = block.children.length;
|
|
|
|
|
|
|
|
// The width and height in number blocks
|
2024-01-08 15:48:59 +01:00
|
|
|
let xSize = block.children.length;
|
2023-10-15 22:21:25 +02:00
|
|
|
if (columns > 0 && columns < numItems) {
|
|
|
|
xSize = columns;
|
|
|
|
}
|
2024-01-18 10:22:09 +01:00
|
|
|
|
|
|
|
const w = block.w || 1;
|
|
|
|
|
2023-10-15 22:21:25 +02:00
|
|
|
const ySize = Math.ceil(numItems / xSize);
|
|
|
|
|
2024-01-08 14:03:42 +01:00
|
|
|
let width = xSize * (maxWidth + padding) + padding;
|
2024-01-08 15:48:59 +01:00
|
|
|
let height = ySize * (maxHeight + padding) + padding;
|
2024-01-08 14:03:42 +01:00
|
|
|
// If maxWidth
|
|
|
|
if (width < sieblingWidth) {
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug(
|
2024-01-18 10:22:09 +01:00
|
|
|
'Detected to small siebling: abc95',
|
2024-01-08 14:03:42 +01:00
|
|
|
block.id,
|
|
|
|
'sieblingWidth',
|
|
|
|
sieblingWidth,
|
2024-01-08 15:48:59 +01:00
|
|
|
'sieblingHeight',
|
|
|
|
sieblingHeight,
|
2024-01-08 14:03:42 +01:00
|
|
|
'width',
|
|
|
|
width
|
|
|
|
);
|
|
|
|
width = sieblingWidth;
|
2024-01-08 15:48:59 +01:00
|
|
|
height = sieblingHeight;
|
2024-01-08 14:03:42 +01:00
|
|
|
const childWidth = (sieblingWidth - xSize * padding - padding) / xSize;
|
2024-01-08 15:48:59 +01:00
|
|
|
const childHeight = (sieblingHeight - ySize * padding - padding) / ySize;
|
2024-01-08 14:03:42 +01:00
|
|
|
log.debug('Size indata abc88', block.id, 'childWidth', childWidth, 'maxWidth', maxWidth);
|
2024-01-08 15:48:59 +01:00
|
|
|
log.debug('Size indata abc88', block.id, 'childHeight', childHeight, 'maxHeight', maxHeight);
|
2024-01-08 14:03:42 +01:00
|
|
|
log.debug('Size indata abc88 xSize', xSize, 'paddiong', padding);
|
|
|
|
|
2024-01-08 15:48:59 +01:00
|
|
|
// set width of block to max width of children
|
2024-01-08 14:03:42 +01:00
|
|
|
for (const child of block.children) {
|
|
|
|
if (child.size) {
|
|
|
|
child.size.width = childWidth;
|
2024-01-08 15:48:59 +01:00
|
|
|
child.size.height = childHeight;
|
2024-01-08 14:03:42 +01:00
|
|
|
child.size.x = 0;
|
|
|
|
child.size.y = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug(
|
2024-01-18 10:22:09 +01:00
|
|
|
'abc95 (finale calc)',
|
2023-10-15 22:21:25 +02:00
|
|
|
block.id,
|
|
|
|
'xSize',
|
|
|
|
xSize,
|
|
|
|
'ySize',
|
|
|
|
ySize,
|
|
|
|
'columns',
|
|
|
|
columns,
|
2024-01-18 10:22:09 +01:00
|
|
|
block.children.length,
|
|
|
|
'width=',
|
|
|
|
Math.max(width, block.size?.width || 0)
|
2023-10-15 22:21:25 +02:00
|
|
|
);
|
2024-01-18 10:22:09 +01:00
|
|
|
if (width < (block?.size?.width || 0)) {
|
|
|
|
width = block?.size?.width || 0;
|
2023-10-15 22:21:25 +02:00
|
|
|
|
2024-01-18 10:22:09 +01:00
|
|
|
// Grow children to fit
|
|
|
|
const num = block.children.length;
|
|
|
|
if (num > 0) {
|
|
|
|
const childWidth = (width - num * padding - padding) / num;
|
2024-01-18 14:28:14 +01:00
|
|
|
// log.debug('abc95 (finale calc) width', block.id, width, block.size?.width, childWidth);
|
2024-01-18 10:22:09 +01:00
|
|
|
for (const child of block.children) {
|
|
|
|
if (child.size) {
|
|
|
|
child.size.width = childWidth;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-10-03 14:19:08 +02:00
|
|
|
block.size = {
|
2024-01-08 14:03:42 +01:00
|
|
|
width,
|
2024-01-08 15:48:59 +01:00
|
|
|
height,
|
2023-10-03 14:19:08 +02:00
|
|
|
x: 0,
|
|
|
|
y: 0,
|
|
|
|
};
|
2023-10-03 12:56:47 +02:00
|
|
|
}
|
2024-01-08 14:03:42 +01:00
|
|
|
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug(
|
2024-01-18 10:22:09 +01:00
|
|
|
'setBlockSizes abc94 (done)',
|
2024-01-08 15:48:59 +01:00
|
|
|
block.id,
|
|
|
|
block?.size?.x,
|
|
|
|
block?.size?.width,
|
|
|
|
block?.size?.y,
|
|
|
|
block?.size?.height
|
|
|
|
);
|
2023-10-03 20:12:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function layoutBlocks(block: Block, db: BlockDB) {
|
2023-10-15 22:21:25 +02:00
|
|
|
log.debug(
|
2024-01-18 14:28:14 +01:00
|
|
|
'abc85 layout blocks (=>layoutBlocks)',
|
2023-10-15 22:21:25 +02:00
|
|
|
block.id,
|
|
|
|
'x:',
|
|
|
|
block?.size?.x,
|
2024-01-08 15:48:59 +01:00
|
|
|
'y:',
|
|
|
|
block?.size?.y,
|
2023-10-15 22:21:25 +02:00
|
|
|
'width:',
|
|
|
|
block?.size?.width
|
|
|
|
);
|
|
|
|
const columns = block.columns || -1;
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug('layoutBlocks columns abc95', block.id, '=>', columns, block);
|
2023-10-03 20:12:33 +02:00
|
|
|
if (
|
|
|
|
block.children && // find max width of children
|
|
|
|
block.children.length > 0
|
|
|
|
) {
|
|
|
|
const width = block?.children[0]?.size?.width || 0;
|
|
|
|
const widthOfChildren = block.children.length * width + (block.children.length - 1) * padding;
|
|
|
|
|
2024-01-08 15:48:59 +01:00
|
|
|
log.debug('widthOfChildren 88', widthOfChildren, 'posX');
|
2023-10-03 20:12:33 +02:00
|
|
|
|
|
|
|
// let first = true;
|
2024-01-08 15:48:59 +01:00
|
|
|
let columnPos = 0;
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug('abc91 block?.size?.x', block.id, block?.size?.x);
|
2024-01-18 10:22:09 +01:00
|
|
|
let startingPosX = block?.size?.x ? block?.size?.x + (-block?.size?.width / 2 || 0) : -padding;
|
|
|
|
let rowPos = 0;
|
2023-10-03 20:12:33 +02:00
|
|
|
for (const child of block.children) {
|
2024-01-18 10:22:09 +01:00
|
|
|
const parent = block;
|
2023-10-03 20:12:33 +02:00
|
|
|
|
|
|
|
if (!child.size) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const { width, height } = child.size;
|
2023-10-15 22:21:25 +02:00
|
|
|
const { px, py } = calculateBlockPosition(columns, columnPos);
|
2024-01-18 10:22:09 +01:00
|
|
|
if (py != rowPos) {
|
|
|
|
rowPos = py;
|
|
|
|
startingPosX = block?.size?.x || -padding;
|
|
|
|
}
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug(
|
2024-01-18 10:22:09 +01:00
|
|
|
'abc89 layout blocks (child) id:',
|
2024-01-08 15:48:59 +01:00
|
|
|
child.id,
|
2024-01-18 10:22:09 +01:00
|
|
|
'Pos:',
|
|
|
|
columnPos,
|
2024-01-08 15:48:59 +01:00
|
|
|
' (px, py)',
|
|
|
|
px,
|
|
|
|
py,
|
|
|
|
' (',
|
2024-01-18 10:22:09 +01:00
|
|
|
parent?.size?.x,
|
2023-10-15 22:21:25 +02:00
|
|
|
',',
|
2024-01-18 10:22:09 +01:00
|
|
|
parent?.size?.y,
|
2023-10-15 22:21:25 +02:00
|
|
|
')',
|
|
|
|
'parent:',
|
2024-01-18 10:22:09 +01:00
|
|
|
parent.id,
|
|
|
|
'width:',
|
|
|
|
width,
|
2023-10-15 22:21:25 +02:00
|
|
|
padding
|
|
|
|
);
|
2024-01-18 10:22:09 +01:00
|
|
|
if (parent.size) {
|
|
|
|
// child.size.x =
|
|
|
|
// block.size.x -
|
|
|
|
// block.size.width / 2 +
|
|
|
|
// px * (child?.w || 1) * (width + padding) +
|
|
|
|
// width / 2 +
|
|
|
|
// padding;
|
|
|
|
const halfWidth = width / 2;
|
|
|
|
child.size.x = startingPosX + padding + halfWidth;
|
|
|
|
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug(
|
2024-01-18 10:22:09 +01:00
|
|
|
'abc91 layout blocks (calc) px, py',
|
|
|
|
'id:',
|
|
|
|
child.id,
|
|
|
|
'startingPosX',
|
|
|
|
startingPosX,
|
|
|
|
'new startingPosX',
|
|
|
|
child.size.x + halfWidth,
|
|
|
|
'padding',
|
|
|
|
padding,
|
|
|
|
'width=',
|
|
|
|
width,
|
|
|
|
'halfWidth',
|
|
|
|
halfWidth,
|
|
|
|
'=>',
|
|
|
|
'x:',
|
|
|
|
child.size.x,
|
|
|
|
'y:',
|
|
|
|
child.size.y,
|
|
|
|
child.w,
|
|
|
|
'(width * (child?.w || 1)) / 2',
|
|
|
|
(width * (child?.w || 1)) / 2
|
|
|
|
);
|
|
|
|
|
|
|
|
startingPosX = child.size.x + halfWidth;
|
|
|
|
|
2023-10-15 22:21:25 +02:00
|
|
|
child.size.y =
|
2024-01-18 10:22:09 +01:00
|
|
|
parent.size.y - parent.size.height / 2 + py * (height + padding) + height / 2 + padding;
|
2023-10-15 22:21:25 +02:00
|
|
|
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug(
|
2024-01-08 15:48:59 +01:00
|
|
|
'abc88 layout blocks (calc) px, py',
|
2023-10-15 22:21:25 +02:00
|
|
|
'id:',
|
|
|
|
child.id,
|
2024-01-18 10:22:09 +01:00
|
|
|
'startingPosX',
|
|
|
|
startingPosX,
|
|
|
|
padding,
|
|
|
|
halfWidth,
|
2023-10-15 22:21:25 +02:00
|
|
|
'=>',
|
|
|
|
'x:',
|
|
|
|
child.size.x,
|
|
|
|
'y:',
|
2024-01-18 10:22:09 +01:00
|
|
|
child.size.y,
|
|
|
|
child.w,
|
|
|
|
'(width * (child?.w || 1)) / 2',
|
|
|
|
(width * (child?.w || 1)) / 2
|
2023-10-15 22:21:25 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-10-03 20:12:33 +02:00
|
|
|
// posY += height + padding;
|
|
|
|
if (child.children) {
|
|
|
|
layoutBlocks(child, db);
|
|
|
|
}
|
2024-01-18 10:22:09 +01:00
|
|
|
columnPos += child?.w || 1;
|
2024-01-18 14:28:14 +01:00
|
|
|
log.debug('abc88 columnsPos', child, columnPos);
|
2023-10-03 20:12:33 +02:00
|
|
|
}
|
|
|
|
}
|
2023-10-15 22:21:25 +02:00
|
|
|
log.debug(
|
|
|
|
'layout blocks (<==layoutBlocks)',
|
2023-10-03 20:12:33 +02:00
|
|
|
block.id,
|
2023-10-15 22:21:25 +02:00
|
|
|
'x:',
|
2023-10-03 20:12:33 +02:00
|
|
|
block?.size?.x,
|
2024-01-08 15:48:59 +01:00
|
|
|
'y:',
|
|
|
|
block?.size?.y,
|
2023-10-03 20:12:33 +02:00
|
|
|
'width:',
|
|
|
|
block?.size?.width
|
|
|
|
);
|
2023-09-05 11:13:27 +02:00
|
|
|
}
|
2023-10-15 22:21:25 +02:00
|
|
|
|
2023-09-05 11:13:27 +02:00
|
|
|
let minX = 0;
|
|
|
|
let minY = 0;
|
|
|
|
let maxX = 0;
|
|
|
|
let maxY = 0;
|
|
|
|
|
|
|
|
function findBounds(block: Block) {
|
2023-10-03 20:12:33 +02:00
|
|
|
if (block.size && block.id !== 'root') {
|
2023-09-05 11:13:27 +02:00
|
|
|
const { x, y, width, height } = block.size;
|
2023-09-14 10:11:43 +02:00
|
|
|
if (x - width / 2 < minX) {
|
|
|
|
minX = x - width / 2;
|
2023-10-15 22:21:25 +02:00
|
|
|
// log.debug('Here APA minX', block.id, x, width, minX);
|
2023-09-05 11:13:27 +02:00
|
|
|
}
|
2023-09-14 10:11:43 +02:00
|
|
|
if (y - height / 2 < minY) {
|
|
|
|
minY = y - height / 2;
|
2023-09-05 11:13:27 +02:00
|
|
|
}
|
2023-09-14 10:11:43 +02:00
|
|
|
if (x + width / 2 > maxX) {
|
|
|
|
maxX = x + width / 2;
|
2023-09-05 11:13:27 +02:00
|
|
|
}
|
2023-09-14 10:11:43 +02:00
|
|
|
if (y + height / 2 > maxY) {
|
|
|
|
maxY = y + height / 2;
|
2023-09-05 11:13:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (block.children) {
|
|
|
|
for (const child of block.children) {
|
|
|
|
findBounds(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function layout(db: BlockDB) {
|
2023-10-15 22:21:25 +02:00
|
|
|
const root = db.getBlock('root');
|
|
|
|
if (!root) {
|
|
|
|
return;
|
|
|
|
}
|
2024-01-08 14:03:42 +01:00
|
|
|
|
2024-01-08 15:48:59 +01:00
|
|
|
setBlockSizes(root, db, 0, 0);
|
2023-10-03 20:12:33 +02:00
|
|
|
layoutBlocks(root, db);
|
2023-10-03 12:56:47 +02:00
|
|
|
// Position blocks relative to parents
|
2023-10-03 20:12:33 +02:00
|
|
|
// positionBlock(root, root, db);
|
2023-10-15 22:21:25 +02:00
|
|
|
log.debug('getBlocks', JSON.stringify(root, null, 2));
|
2023-09-05 11:13:27 +02:00
|
|
|
|
|
|
|
minX = 0;
|
|
|
|
minY = 0;
|
|
|
|
maxX = 0;
|
|
|
|
maxY = 0;
|
|
|
|
findBounds(root);
|
2023-10-15 22:21:25 +02:00
|
|
|
// log.debug('Here maxX', minX, '--', maxX);
|
2023-09-05 11:13:27 +02:00
|
|
|
const height = maxY - minY;
|
|
|
|
const width = maxX - minX;
|
|
|
|
return { x: minX, y: minY, width, height };
|
|
|
|
}
|