249 lines
7.0 KiB
TypeScript
249 lines
7.0 KiB
TypeScript
import type { Direction } from '../../src/diagrams/block/blockTypes.js';
|
|
|
|
const expandAndDeduplicateDirections = (directions: Direction[]) => {
|
|
const uniqueDirections = new Set();
|
|
|
|
for (const direction of directions) {
|
|
switch (direction) {
|
|
case 'x':
|
|
uniqueDirections.add('right');
|
|
uniqueDirections.add('left');
|
|
break;
|
|
case 'y':
|
|
uniqueDirections.add('up');
|
|
uniqueDirections.add('down');
|
|
break;
|
|
default:
|
|
uniqueDirections.add(direction);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return uniqueDirections;
|
|
};
|
|
export const getArrowPoints = (
|
|
duplicatedDirections: Direction[],
|
|
bbox: { width: number; height: number },
|
|
node: any
|
|
) => {
|
|
// Expand and deduplicate the provided directions.
|
|
// for instance: x, right => right, left
|
|
const directions = expandAndDeduplicateDirections(duplicatedDirections);
|
|
|
|
// Factor to divide height for some calculations.
|
|
const f = 2;
|
|
|
|
// Calculated height of the bounding box, accounting for node padding.
|
|
const height = bbox.height + 2 * node.padding;
|
|
// Midpoint calculation based on height.
|
|
const midpoint = height / f;
|
|
// Calculated width of the bounding box, accounting for additional width and node padding.
|
|
const width = bbox.width + 2 * midpoint + node.padding;
|
|
// Padding to use, half of the node padding.
|
|
const padding = node.padding / 2;
|
|
|
|
// Initialize an empty array to store points for the arrow.
|
|
const points = [];
|
|
|
|
if (
|
|
directions.has('right') &&
|
|
directions.has('left') &&
|
|
directions.has('up') &&
|
|
directions.has('down')
|
|
) {
|
|
// SQUARE
|
|
return [
|
|
// Bottom
|
|
{ x: 0, y: 0 },
|
|
{ x: midpoint, y: 0 },
|
|
{ x: width / 2, y: 2 * padding },
|
|
{ x: width - midpoint, y: 0 },
|
|
{ x: width, y: 0 },
|
|
|
|
// Right
|
|
{ x: width, y: -height / 3 },
|
|
{ x: width + 2 * padding, y: -height / 2 },
|
|
{ x: width, y: (-2 * height) / 3 },
|
|
{ x: width, y: -height },
|
|
|
|
// Top
|
|
{ x: width - midpoint, y: -height },
|
|
{ x: width / 2, y: -height - 2 * padding },
|
|
{ x: midpoint, y: -height },
|
|
|
|
// Left
|
|
{ x: 0, y: -height },
|
|
{ x: 0, y: (-2 * height) / 3 },
|
|
{ x: -2 * padding, y: -height / 2 },
|
|
{ x: 0, y: -height / 3 },
|
|
];
|
|
}
|
|
if (directions.has('right') && directions.has('left') && directions.has('up')) {
|
|
// RECTANGLE_VERTICAL (Top Open)
|
|
return [
|
|
{ x: midpoint, y: 0 },
|
|
{ x: width - midpoint, y: 0 },
|
|
{ x: width, y: -height / 2 },
|
|
{ x: width - midpoint, y: -height },
|
|
{ x: midpoint, y: -height },
|
|
{ x: 0, y: -height / 2 },
|
|
];
|
|
}
|
|
if (directions.has('right') && directions.has('left') && directions.has('down')) {
|
|
// RECTANGLE_VERTICAL (Bottom Open)
|
|
return [
|
|
{ x: 0, y: 0 },
|
|
{ x: midpoint, y: -height },
|
|
{ x: width - midpoint, y: -height },
|
|
{ x: width, y: 0 },
|
|
];
|
|
}
|
|
if (directions.has('right') && directions.has('up') && directions.has('down')) {
|
|
// RECTANGLE_HORIZONTAL (Right Open)
|
|
return [
|
|
{ x: 0, y: 0 },
|
|
{ x: width, y: -midpoint },
|
|
{ x: width, y: -height + midpoint },
|
|
{ x: 0, y: -height },
|
|
];
|
|
}
|
|
if (directions.has('left') && directions.has('up') && directions.has('down')) {
|
|
// RECTANGLE_HORIZONTAL (Left Open)
|
|
return [
|
|
{ x: width, y: 0 },
|
|
{ x: 0, y: -midpoint },
|
|
{ x: 0, y: -height + midpoint },
|
|
{ x: width, y: -height },
|
|
];
|
|
}
|
|
if (directions.has('right') && directions.has('left')) {
|
|
// HORIZONTAL_LINE
|
|
return [
|
|
{ x: midpoint, y: 0 },
|
|
{ x: midpoint, y: -padding },
|
|
{ x: width - midpoint, y: -padding },
|
|
{ x: width - midpoint, y: 0 },
|
|
{ x: width, y: -height / 2 },
|
|
{ x: width - midpoint, y: -height },
|
|
{ x: width - midpoint, y: -height + padding },
|
|
{ x: midpoint, y: -height + padding },
|
|
{ x: midpoint, y: -height },
|
|
{ x: 0, y: -height / 2 },
|
|
];
|
|
}
|
|
if (directions.has('up') && directions.has('down')) {
|
|
// VERTICAL_LINE
|
|
return [
|
|
// Bottom center
|
|
{ x: width / 2, y: 0 },
|
|
// Left pont of bottom arrow
|
|
{ x: 0, y: -padding },
|
|
{ x: midpoint, y: -padding },
|
|
// Left top over vertical section
|
|
{ x: midpoint, y: -height + padding },
|
|
{ x: 0, y: -height + padding },
|
|
// Top of arrow
|
|
{ x: width / 2, y: -height },
|
|
{ x: width, y: -height + padding },
|
|
// Top of right vertical bar
|
|
{ x: width - midpoint, y: -height + padding },
|
|
{ x: width - midpoint, y: -padding },
|
|
{ x: width, y: -padding },
|
|
];
|
|
}
|
|
if (directions.has('right') && directions.has('up')) {
|
|
// ANGLE_RT
|
|
return [
|
|
{ x: 0, y: 0 },
|
|
{ x: width, y: -midpoint },
|
|
{ x: 0, y: -height },
|
|
];
|
|
}
|
|
if (directions.has('right') && directions.has('down')) {
|
|
// ANGLE_RB
|
|
return [
|
|
{ x: 0, y: 0 },
|
|
{ x: width, y: 0 },
|
|
{ x: 0, y: -height },
|
|
];
|
|
}
|
|
if (directions.has('left') && directions.has('up')) {
|
|
// ANGLE_LT
|
|
return [
|
|
{ x: width, y: 0 },
|
|
{ x: 0, y: -midpoint },
|
|
{ x: width, y: -height },
|
|
];
|
|
}
|
|
if (directions.has('left') && directions.has('down')) {
|
|
// ANGLE_LB
|
|
return [
|
|
{ x: width, y: 0 },
|
|
{ x: 0, y: 0 },
|
|
{ x: width, y: -height },
|
|
];
|
|
}
|
|
if (directions.has('right')) {
|
|
// ARROW_RIGHT
|
|
return [
|
|
{ x: midpoint, y: -padding },
|
|
{ x: midpoint, y: -padding },
|
|
{ x: width - midpoint, y: -padding },
|
|
{ x: width - midpoint, y: 0 },
|
|
{ x: width, y: -height / 2 },
|
|
{ x: width - midpoint, y: -height },
|
|
{ x: width - midpoint, y: -height + padding },
|
|
// top left corner of arrow
|
|
{ x: midpoint, y: -height + padding },
|
|
{ x: midpoint, y: -height + padding },
|
|
];
|
|
}
|
|
if (directions.has('left')) {
|
|
// ARROW_LEFT
|
|
return [
|
|
{ x: midpoint, y: 0 },
|
|
{ x: midpoint, y: -padding },
|
|
// Two points, the right corners
|
|
{ x: width - midpoint, y: -padding },
|
|
{ x: width - midpoint, y: -height + padding },
|
|
{ x: midpoint, y: -height + padding },
|
|
{ x: midpoint, y: -height },
|
|
{ x: 0, y: -height / 2 },
|
|
];
|
|
}
|
|
if (directions.has('up')) {
|
|
// ARROW_TOP
|
|
return [
|
|
// Bottom center
|
|
{ x: midpoint, y: -padding },
|
|
// Left top over vertical section
|
|
{ x: midpoint, y: -height + padding },
|
|
{ x: 0, y: -height + padding },
|
|
// Top of arrow
|
|
{ x: width / 2, y: -height },
|
|
{ x: width, y: -height + padding },
|
|
// Top of right vertical bar
|
|
{ x: width - midpoint, y: -height + padding },
|
|
{ x: width - midpoint, y: -padding },
|
|
];
|
|
}
|
|
if (directions.has('down')) {
|
|
// ARROW_BOTTOM
|
|
return [
|
|
// Bottom center
|
|
{ x: width / 2, y: 0 },
|
|
// Left pont of bottom arrow
|
|
{ x: 0, y: -padding },
|
|
{ x: midpoint, y: -padding },
|
|
// Left top over vertical section
|
|
{ x: midpoint, y: -height + padding },
|
|
{ x: width - midpoint, y: -height + padding },
|
|
{ x: width - midpoint, y: -padding },
|
|
{ x: width, y: -padding },
|
|
];
|
|
}
|
|
|
|
// POINT
|
|
return [{ x: 0, y: 0 }];
|
|
};
|