mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-08 01:56:42 +02:00
Compare commits
5 Commits
mermaid@11
...
6097-elk-g
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8277579259 | ||
![]() |
8336d1cf2d | ||
![]() |
3c93e4640a | ||
![]() |
0c28593ea5 | ||
![]() |
33d8b1a78d |
102
cypress/platform/shape-tester.html
Normal file
102
cypress/platform/shape-tester.html
Normal file
@@ -0,0 +1,102 @@
|
||||
<html>
|
||||
<head>
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Arial';
|
||||
background-color: #333;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="diagram"></div>
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
import layouts from './mermaid-layout-elk.esm.mjs';
|
||||
mermaid.registerLayoutLoaders(layouts);
|
||||
mermaid.parseError = function (err, hash) {
|
||||
console.error('Mermaid error: ', err);
|
||||
};
|
||||
mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
//look: 'handdrawn',
|
||||
// layout: 'fixed',
|
||||
theme: 'dark',
|
||||
//layout: 'elk',
|
||||
fontFamily: 'Kalam',
|
||||
logLevel: 1,
|
||||
});
|
||||
|
||||
let shape = 'card';
|
||||
// let simplified = true;
|
||||
let simplified = false;
|
||||
let algorithm = 'elk';
|
||||
// let algorithm = 'dagre';
|
||||
let code = `---
|
||||
config:
|
||||
layout: ${algorithm}
|
||||
---
|
||||
flowchart TD
|
||||
A["Abrakadabra"] --> C["C"] & D["I am a circle"] & n4["Untitled Node"]
|
||||
D@{ shape: diamond}
|
||||
B["Bombrakadombra"] --> D & C & D
|
||||
C --> E["E"] & B
|
||||
D --> E & A
|
||||
n4 --> C
|
||||
A@{ shape: ${shape}}
|
||||
B@{ shape: ${shape}}
|
||||
C@{ shape: ${shape}}
|
||||
D@{ shape: ${shape}}
|
||||
E@{ shape: ${shape}}
|
||||
n4@{ shape: ${shape}}
|
||||
|
||||
`;
|
||||
if (simplified) {
|
||||
code = `---
|
||||
config:
|
||||
layout: ${algorithm}
|
||||
---
|
||||
flowchart LR
|
||||
A["Abrakadabra"] --> C["C"] & C & C & C & C
|
||||
%% A["Abrakadabra"] --> C
|
||||
A@{ shape: ${shape}}
|
||||
C@{ shape: ${shape}}
|
||||
|
||||
`;
|
||||
}
|
||||
console.log(code);
|
||||
const { svg } = await mermaid.render('the-id-of-the-svg', code, undefined, undefined);
|
||||
const elem = document.querySelector('#diagram');
|
||||
elem.innerHTML = svg;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@@ -592,9 +592,10 @@ export const render = async (
|
||||
setIncludeChildrenPolicy(target, ancestorId);
|
||||
}
|
||||
});
|
||||
|
||||
// const copy = JSON.parse(JSON.stringify({ ...elkGraph }));
|
||||
// console.log('APA13 layout before', copy);
|
||||
const g = await elk.layout(elkGraph);
|
||||
|
||||
// console.log('APA13 layout', JSON.parse(JSON.stringify(g)));
|
||||
// debugger;
|
||||
await drawNodes(0, 0, g.children, svg, subGraphsEl, 0);
|
||||
g.edges?.map(
|
||||
@@ -683,6 +684,18 @@ export const render = async (
|
||||
}
|
||||
|
||||
if (startNode.calcIntersect) {
|
||||
// console.log(
|
||||
// 'APA13 calculating start intersection start node',
|
||||
// startNode.id,
|
||||
// startNode.x,
|
||||
// startNode.y,
|
||||
// 'w:',
|
||||
// startNode.width,
|
||||
// 'h:',
|
||||
// startNode.height,
|
||||
// '\nPos',
|
||||
// edge.points[0]
|
||||
// );
|
||||
const intersection = startNode.calcIntersect(
|
||||
{
|
||||
x: startNode.offset.posX + startNode.width / 2,
|
||||
@@ -707,9 +720,18 @@ export const render = async (
|
||||
},
|
||||
edge.points[edge.points.length - 1]
|
||||
);
|
||||
// if (edge.id === 'L_n4_C_10_0') {
|
||||
// console.log('APA14 lineData', edge.points, 'intersection:', intersection);
|
||||
// console.log(
|
||||
// 'APA14! calculating end intersection\ndistance:',
|
||||
// distance(intersection, edge.points[edge.points.length - 1])
|
||||
// );
|
||||
// }
|
||||
|
||||
if (distance(intersection, edge.points[edge.points.length - 1]) > epsilon) {
|
||||
// console.log('APA13! distance ok\nintersection:', intersection);
|
||||
edge.points.push(intersection);
|
||||
// console.log('APA13! distance ok\npoints:', edge.points);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,8 @@ import { createText } from '../createText.js';
|
||||
import utils from '../../utils.js';
|
||||
import { getLineFunctionsWithOffset } from '../../utils/lineWithOffset.js';
|
||||
import { getSubGraphTitleMargins } from '../../utils/subGraphTitleMargins.js';
|
||||
import { curveBasis, line, select } from 'd3';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import { curveBasis, curveLinear, line, select } from 'd3';
|
||||
import rough from 'roughjs';
|
||||
import createLabel from './createLabel.js';
|
||||
import { addEdgeMarkers } from './edgeMarker.ts';
|
||||
@@ -335,7 +336,7 @@ const cutPathAtIntersect = (_points, boundaryNode) => {
|
||||
return points;
|
||||
};
|
||||
|
||||
const adjustForArrowHeads = function (lineData, size = 5) {
|
||||
const adjustForArrowHeads = function (lineData, size = 5, shouldLog = false) {
|
||||
const newLineData = [...lineData];
|
||||
const lastPoint = lineData[lineData.length - 1];
|
||||
const secondLastPoint = lineData[lineData.length - 2];
|
||||
@@ -344,6 +345,9 @@ const adjustForArrowHeads = function (lineData, size = 5) {
|
||||
(lastPoint.x - secondLastPoint.x) ** 2 + (lastPoint.y - secondLastPoint.y) ** 2
|
||||
);
|
||||
|
||||
if (shouldLog) {
|
||||
log.debug('APA14 distanceBetweenLastPoints', distanceBetweenLastPoints);
|
||||
}
|
||||
if (distanceBetweenLastPoints < size) {
|
||||
// Calculate the direction vector from the last point to the second last point
|
||||
const directionX = secondLastPoint.x - lastPoint.x;
|
||||
@@ -366,6 +370,195 @@ const adjustForArrowHeads = function (lineData, size = 5) {
|
||||
|
||||
return newLineData;
|
||||
};
|
||||
function extractCornerPoints(points) {
|
||||
const cornerPoints = [];
|
||||
const cornerPointPositions = [];
|
||||
for (let i = 1; i < points.length - 1; i++) {
|
||||
const prev = points[i - 1];
|
||||
const curr = points[i];
|
||||
const next = points[i + 1];
|
||||
if (
|
||||
prev.x === curr.x &&
|
||||
curr.y === next.y &&
|
||||
Math.abs(curr.x - next.x) > 5 &&
|
||||
Math.abs(curr.y - prev.y) > 5
|
||||
) {
|
||||
cornerPoints.push(curr);
|
||||
cornerPointPositions.push(i);
|
||||
} else if (
|
||||
prev.y === curr.y &&
|
||||
curr.x === next.x &&
|
||||
Math.abs(curr.x - prev.x) > 5 &&
|
||||
Math.abs(curr.y - next.y) > 5
|
||||
) {
|
||||
cornerPoints.push(curr);
|
||||
cornerPointPositions.push(i);
|
||||
}
|
||||
}
|
||||
return { cornerPoints, cornerPointPositions };
|
||||
}
|
||||
|
||||
const findAdjacentPoint = function (pointA, pointB, distance) {
|
||||
const xDiff = pointB.x - pointA.x;
|
||||
const yDiff = pointB.y - pointA.y;
|
||||
const length = Math.sqrt(xDiff * xDiff + yDiff * yDiff);
|
||||
const ratio = distance / length;
|
||||
return { x: pointB.x - ratio * xDiff, y: pointB.y - ratio * yDiff };
|
||||
};
|
||||
|
||||
const fixCorners = function (lineData) {
|
||||
const { cornerPointPositions } = extractCornerPoints(lineData);
|
||||
const newLineData = [];
|
||||
for (let i = 0; i < lineData.length; i++) {
|
||||
if (cornerPointPositions.includes(i)) {
|
||||
const prevPoint = lineData[i - 1];
|
||||
const nextPoint = lineData[i + 1];
|
||||
const cornerPoint = lineData[i];
|
||||
|
||||
const newPrevPoint = findAdjacentPoint(prevPoint, cornerPoint, 5);
|
||||
const newNextPoint = findAdjacentPoint(nextPoint, cornerPoint, 5);
|
||||
|
||||
const xDiff = newNextPoint.x - newPrevPoint.x;
|
||||
const yDiff = newNextPoint.y - newPrevPoint.y;
|
||||
newLineData.push(newPrevPoint);
|
||||
|
||||
const a = Math.sqrt(2) * 2;
|
||||
let newCornerPoint = { x: cornerPoint.x, y: cornerPoint.y };
|
||||
if (Math.abs(nextPoint.x - prevPoint.x) > 10 && Math.abs(nextPoint.y - prevPoint.y) >= 10) {
|
||||
log.debug(
|
||||
'Corner point fixing',
|
||||
Math.abs(nextPoint.x - prevPoint.x),
|
||||
Math.abs(nextPoint.y - prevPoint.y)
|
||||
);
|
||||
const r = 5;
|
||||
if (cornerPoint.x === newPrevPoint.x) {
|
||||
newCornerPoint = {
|
||||
x: xDiff < 0 ? newPrevPoint.x - r + a : newPrevPoint.x + r - a,
|
||||
y: yDiff < 0 ? newPrevPoint.y - a : newPrevPoint.y + a,
|
||||
};
|
||||
} else {
|
||||
newCornerPoint = {
|
||||
x: xDiff < 0 ? newPrevPoint.x - a : newPrevPoint.x + a,
|
||||
y: yDiff < 0 ? newPrevPoint.y - r + a : newPrevPoint.y + r - a,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
log.debug(
|
||||
'Corner point skipping fixing',
|
||||
Math.abs(nextPoint.x - prevPoint.x),
|
||||
Math.abs(nextPoint.y - prevPoint.y)
|
||||
);
|
||||
}
|
||||
newLineData.push(newCornerPoint, newNextPoint);
|
||||
} else {
|
||||
newLineData.push(lineData[i]);
|
||||
}
|
||||
}
|
||||
return newLineData;
|
||||
};
|
||||
|
||||
export const generateRoundedPath = (points, radius, endPosition) => {
|
||||
if (points.length < 2) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// console.trace('here', points);
|
||||
const path = [];
|
||||
const startPoint = points[0];
|
||||
|
||||
path.push(`M ${startPoint.x},${startPoint.y}`);
|
||||
|
||||
for (let i = 1; i < points.length - 1; i++) {
|
||||
const currPoint = points[i];
|
||||
const nextPoint = points[i + 1];
|
||||
const prevPoint = points[i - 1];
|
||||
|
||||
// Calculate vectors
|
||||
const v1 = { x: currPoint.x - prevPoint.x, y: currPoint.y - prevPoint.y };
|
||||
const v2 = { x: nextPoint.x - currPoint.x, y: nextPoint.y - currPoint.y };
|
||||
|
||||
// Normalize vectors
|
||||
const v1Length = Math.hypot(v1.x, v1.y);
|
||||
const v2Length = Math.hypot(v2.x, v2.y);
|
||||
const v1Normalized = { x: v1.x / v1Length, y: v1.y / v1Length };
|
||||
const v2Normalized = { x: v2.x / v2Length, y: v2.y / v2Length };
|
||||
|
||||
// Calculate tangent points
|
||||
const tangentLength = Math.min(radius, v1Length / 2, v2Length / 2);
|
||||
const tangent1 = {
|
||||
x: currPoint.x - v1Normalized.x * tangentLength,
|
||||
y: currPoint.y - v1Normalized.y * tangentLength,
|
||||
};
|
||||
const tangent2 = {
|
||||
x: currPoint.x + v2Normalized.x * tangentLength,
|
||||
y: currPoint.y + v2Normalized.y * tangentLength,
|
||||
};
|
||||
|
||||
if (endPosition) {
|
||||
const { bottomY, leftX, rightX, topY } = endPosition;
|
||||
if (startPoint.pos === 'b' && tangent1.y > topY) {
|
||||
tangent1.y = topY;
|
||||
tangent2.y = topY;
|
||||
currPoint.y = topY;
|
||||
}
|
||||
if (startPoint.pos === 't' && tangent1.y < bottomY) {
|
||||
tangent1.y = bottomY;
|
||||
tangent2.y = bottomY;
|
||||
currPoint.y = bottomY;
|
||||
}
|
||||
if (startPoint.pos === 'l' && tangent1.x < rightX) {
|
||||
tangent1.x = rightX;
|
||||
tangent2.x = rightX;
|
||||
currPoint.x = rightX;
|
||||
}
|
||||
if (startPoint.pos === 'r' && tangent1.x > leftX) {
|
||||
tangent1.x = leftX;
|
||||
tangent2.x = leftX;
|
||||
currPoint.x = leftX;
|
||||
}
|
||||
if (tangent2.x && tangent2.y && tangent1.x && tangent1.y) {
|
||||
path.push(
|
||||
`L ${tangent1.x},${tangent1.y}`,
|
||||
`Q ${currPoint.x},${currPoint.y} ${tangent2.x},${tangent2.y}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (tangent2.x && tangent2.y && tangent1.x && tangent1.y) {
|
||||
path.push(
|
||||
`L ${tangent1.x},${tangent1.y}`,
|
||||
`Q ${currPoint.x},${currPoint.y} ${tangent2.x},${tangent2.y}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Last point
|
||||
const lastPoint = points[points.length - 1];
|
||||
if (endPosition) {
|
||||
if (startPoint.pos === 'b') {
|
||||
if (endPosition?.topY && points[1].y > endPosition?.topY && points[2].y > endPosition?.topY) {
|
||||
points[1].y = endPosition?.topY;
|
||||
points[2].y = endPosition?.topY;
|
||||
}
|
||||
path.push(`L ${lastPoint.x},${endPosition.topY}`);
|
||||
}
|
||||
if (startPoint.pos === 't') {
|
||||
if (points[1].y < endPosition.bottomY) {
|
||||
points[1].y = endPosition.bottomY;
|
||||
points[2].y = endPosition.bottomY;
|
||||
}
|
||||
path.push(`L ${lastPoint.x},${endPosition.bottomY}`);
|
||||
}
|
||||
if (startPoint.pos === 'l') {
|
||||
path.push(`L ${endPosition.rightX},${lastPoint.y}`);
|
||||
}
|
||||
if (startPoint.pos === 'r') {
|
||||
path.push(`L ${endPosition.leftX},${lastPoint.y}`);
|
||||
}
|
||||
} else {
|
||||
path.push(`L ${lastPoint.x},${lastPoint.y}`);
|
||||
}
|
||||
return path.join(' ');
|
||||
};
|
||||
|
||||
export const insertEdge = function (elem, edge, clusterDb, diagramType, startNode, endNode, id) {
|
||||
const { handDrawnSeed } = getConfig();
|
||||
@@ -407,8 +600,12 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
}
|
||||
|
||||
let lineData = points.filter((p) => !Number.isNaN(p.y));
|
||||
lineData = adjustForArrowHeads(lineData);
|
||||
// lineData = fixCorners(lineData);
|
||||
lineData = adjustForArrowHeads(lineData, 4, edge.id === 'L_n4_C_10_0');
|
||||
lineData = fixCorners(lineData);
|
||||
// if (edge.id === 'L_n4_C_10_0') {
|
||||
// console.log('APA14 lineData', lineData);
|
||||
// }
|
||||
// lineData = adjustForArrowHeads(lineData);
|
||||
let curve = curveBasis;
|
||||
// let curve = curveLinear;
|
||||
if (edge.curve) {
|
||||
@@ -417,6 +614,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
|
||||
const { x, y } = getLineFunctionsWithOffset(edge);
|
||||
const lineFunction = line().x(x).y(y).curve(curve);
|
||||
// const lineFunction = line().curve(curve);
|
||||
|
||||
let strokeClasses;
|
||||
switch (edge.thickness) {
|
||||
@@ -447,6 +645,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
}
|
||||
let svgPath;
|
||||
let linePath = lineFunction(lineData);
|
||||
// let linePath = generateRoundedPath(lineData, 5);
|
||||
const edgeStyles = Array.isArray(edge.style) ? edge.style : [edge.style];
|
||||
if (edge.look === 'handDrawn') {
|
||||
const rc = rough.svg(elem);
|
||||
@@ -478,16 +677,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
|
||||
// DEBUG code, DO NOT REMOVE
|
||||
// adds a red circle at each edge coordinate
|
||||
// cornerPoints.forEach((point) => {
|
||||
// elem
|
||||
// .append('circle')
|
||||
// .style('stroke', 'blue')
|
||||
// .style('fill', 'blue')
|
||||
// .attr('r', 3)
|
||||
// .attr('cx', point.x)
|
||||
// .attr('cy', point.y);
|
||||
// });
|
||||
// lineData.forEach((point) => {
|
||||
// points.forEach((point) => {
|
||||
// elem
|
||||
// .append('circle')
|
||||
// .style('stroke', 'red')
|
||||
|
@@ -57,7 +57,7 @@ function intersectLine(p1, p2, q1, q2) {
|
||||
num = a2 * c1 - a1 * c2;
|
||||
const y = num < 0 ? (num - offset) / denom : (num + offset) / denom;
|
||||
// console.log(
|
||||
// 'APA30 intersectLine intersection',
|
||||
// 'APA13 intersectLine intersection',
|
||||
// '\np1: (',
|
||||
// p1.x,
|
||||
// p1.y,
|
||||
|
@@ -7,7 +7,7 @@ import intersectLine from './intersect-line.js';
|
||||
function intersectPolygon(node, polyPoints, point) {
|
||||
let x1 = node.x;
|
||||
let y1 = node.y;
|
||||
|
||||
// console.trace('APA14 intersectPolygon', x1, y1, polyPoints, point);
|
||||
let intersections = [];
|
||||
|
||||
let minX = Number.POSITIVE_INFINITY;
|
||||
@@ -24,7 +24,7 @@ function intersectPolygon(node, polyPoints, point) {
|
||||
|
||||
let left = x1 - node.width / 2 - minX;
|
||||
let top = y1 - node.height / 2 - minY;
|
||||
|
||||
// console.log('APA13 intersectPolygon2 ', left, y1);
|
||||
for (let i = 0; i < polyPoints.length; i++) {
|
||||
let p1 = polyPoints[i];
|
||||
let p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0];
|
||||
@@ -34,7 +34,9 @@ function intersectPolygon(node, polyPoints, point) {
|
||||
{ x: left + p1.x, y: top + p1.y },
|
||||
{ x: left + p2.x, y: top + p2.y }
|
||||
);
|
||||
// console.log('APA13 intersectPolygon3 ', intersect);
|
||||
if (intersect) {
|
||||
// console.log('APA13 intersectPolygon4 ', intersect);
|
||||
intersections.push(intersect);
|
||||
}
|
||||
}
|
||||
@@ -42,6 +44,7 @@ function intersectPolygon(node, polyPoints, point) {
|
||||
if (!intersections.length) {
|
||||
return node;
|
||||
}
|
||||
// console.log('APA12 intersectPolygon5 ');
|
||||
|
||||
if (intersections.length > 1) {
|
||||
// More intersections, find the one nearest to edge end point
|
||||
@@ -54,6 +57,8 @@ function intersectPolygon(node, polyPoints, point) {
|
||||
let qdy = q.y - point.y;
|
||||
let distq = Math.sqrt(qdx * qdx + qdy * qdy);
|
||||
|
||||
// console.log('APA12 intersectPolygon6 ');
|
||||
|
||||
return distp < distq ? -1 : distp === distq ? 0 : 1;
|
||||
});
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import { handleUndefinedAttr } from '../../../utils.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export function anchor<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles } = styles2String(node);
|
||||
@@ -37,6 +38,11 @@ export function anchor<T extends SVGGraphicsElement>(parent: D3Selection<T>, nod
|
||||
|
||||
updateNodeBounds(node, circleElem);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('Circle intersect', node, radius, point);
|
||||
return intersect.circle(node, radius, point);
|
||||
|
@@ -4,6 +4,7 @@ import type { Node } from '../../types.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
function generateArcPoints(
|
||||
x1: number,
|
||||
@@ -70,7 +71,15 @@ function generateArcPoints(
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
function getPoints(w: number, h: number, rx: number, ry: number) {
|
||||
return [
|
||||
{ x: w / 2, y: -h / 2 },
|
||||
{ x: -w / 2, y: -h / 2 },
|
||||
...generateArcPoints(-w / 2, -h / 2, -w / 2, h / 2, rx, ry, false),
|
||||
{ x: w / 2, y: h / 2 },
|
||||
...generateArcPoints(w / 2, h / 2, w / 2, -h / 2, rx, ry, true),
|
||||
];
|
||||
}
|
||||
export async function bowTieRect<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles, nodeStyles } = styles2String(node);
|
||||
node.labelStyle = labelStyles;
|
||||
@@ -84,13 +93,7 @@ export async function bowTieRect<T extends SVGGraphicsElement>(parent: D3Selecti
|
||||
// let shape: d3.Selection<SVGPathElement | SVGGElement, unknown, null, undefined>;
|
||||
const { cssStyles } = node;
|
||||
|
||||
const points = [
|
||||
{ x: w / 2, y: -h / 2 },
|
||||
{ x: -w / 2, y: -h / 2 },
|
||||
...generateArcPoints(-w / 2, -h / 2, -w / 2, h / 2, rx, ry, false),
|
||||
{ x: w / 2, y: h / 2 },
|
||||
...generateArcPoints(w / 2, h / 2, w / 2, -h / 2, rx, ry, true),
|
||||
];
|
||||
const points = getPoints(w, h, rx, ry);
|
||||
|
||||
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||
const rc = rough.svg(shapeSvg);
|
||||
@@ -118,6 +121,16 @@ export async function bowTieRect<T extends SVGGraphicsElement>(parent: D3Selecti
|
||||
|
||||
updateNodeBounds(node, bowTieRectShape);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const w = bounds.width;
|
||||
const h = bounds.height;
|
||||
|
||||
const ry = h / 2;
|
||||
const rx = ry / (2.5 + h / 50);
|
||||
|
||||
const points = getPoints(w, h, rx, ry);
|
||||
return intersect.polygon(bounds, points, point);
|
||||
};
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, points, point);
|
||||
return pos;
|
||||
|
@@ -3,17 +3,25 @@ import intersect from '../intersect/index.js';
|
||||
import type { Node } from '../../types.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
|
||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||
import { createPathFromPoints } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
// const createPathFromPoints = (points: { x: number; y: number }[]): string => {
|
||||
// const pointStrings = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`);
|
||||
// pointStrings.push('Z');
|
||||
// return pointStrings.join(' ');
|
||||
// };
|
||||
|
||||
function getPoints(w: number, h: number, padding: number) {
|
||||
const left = 0;
|
||||
const right = w;
|
||||
const top = -h;
|
||||
const bottom = 0;
|
||||
return [
|
||||
{ x: left + padding, y: top },
|
||||
{ x: right, y: top },
|
||||
{ x: right, y: bottom },
|
||||
{ x: left, y: bottom },
|
||||
{ x: left, y: top + padding },
|
||||
{ x: left + padding, y: top },
|
||||
];
|
||||
}
|
||||
export async function card<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles, nodeStyles } = styles2String(node);
|
||||
node.labelStyle = labelStyles;
|
||||
@@ -22,18 +30,8 @@ export async function card<T extends SVGGraphicsElement>(parent: D3Selection<T>,
|
||||
const h = bbox.height + node.padding;
|
||||
const padding = 12;
|
||||
const w = bbox.width + node.padding + padding;
|
||||
const left = 0;
|
||||
const right = w;
|
||||
const top = -h;
|
||||
const bottom = 0;
|
||||
const points = [
|
||||
{ x: left + padding, y: top },
|
||||
{ x: right, y: top },
|
||||
{ x: right, y: bottom },
|
||||
{ x: left, y: bottom },
|
||||
{ x: left, y: top + padding },
|
||||
{ x: left + padding, y: top },
|
||||
];
|
||||
|
||||
const points = getPoints(w, h, padding);
|
||||
|
||||
let polygon: D3Selection<SVGGElement> | Awaited<ReturnType<typeof insertPolygonShape>>;
|
||||
const { cssStyles } = node;
|
||||
@@ -62,6 +60,17 @@ export async function card<T extends SVGGraphicsElement>(parent: D3Selection<T>,
|
||||
|
||||
updateNodeBounds(node, polygon);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const h = bounds.height;
|
||||
const padding = 12;
|
||||
const w = bounds.width;
|
||||
|
||||
const points = getPoints(w, h, padding);
|
||||
|
||||
const res = intersect.polygon(bounds, points, point);
|
||||
return { x: res.x - 0.5, y: res.y - 0.5 };
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.polygon(node, points, point);
|
||||
};
|
||||
|
@@ -4,7 +4,15 @@ import rough from 'roughjs';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import { createPathFromPoints, getNodeClasses } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
function getPoints(s: number) {
|
||||
return [
|
||||
{ x: 0, y: s / 2 },
|
||||
{ x: s / 2, y: 0 },
|
||||
{ x: 0, y: -s / 2 },
|
||||
{ x: -s / 2, y: 0 },
|
||||
];
|
||||
}
|
||||
export function choice<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { nodeStyles } = styles2String(node);
|
||||
node.label = '';
|
||||
@@ -16,12 +24,7 @@ export function choice<T extends SVGGraphicsElement>(parent: D3Selection<T>, nod
|
||||
|
||||
const s = Math.max(28, node.width ?? 0);
|
||||
|
||||
const points = [
|
||||
{ x: 0, y: s / 2 },
|
||||
{ x: s / 2, y: 0 },
|
||||
{ x: 0, y: -s / 2 },
|
||||
{ x: -s / 2, y: 0 },
|
||||
];
|
||||
const points = getPoints(s);
|
||||
|
||||
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||
const rc = rough.svg(shapeSvg);
|
||||
@@ -47,6 +50,13 @@ export function choice<T extends SVGGraphicsElement>(parent: D3Selection<T>, nod
|
||||
node.width = 28;
|
||||
node.height = 28;
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const s = Math.max(28, bounds.width ?? 0);
|
||||
|
||||
const points = getPoints(s);
|
||||
return intersect.circle(bounds, points, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.polygon(node, points, point);
|
||||
};
|
||||
|
@@ -9,6 +9,7 @@ import intersect from '../intersect/index.js';
|
||||
import { textHelper } from '../../../diagrams/class/shapeUtil.js';
|
||||
import { evaluate } from '../../../diagrams/common/common.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function classBox<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const config = getConfig();
|
||||
@@ -199,6 +200,9 @@ export async function classBox<T extends SVGGraphicsElement>(parent: D3Selection
|
||||
}
|
||||
|
||||
updateNodeBounds(node, rect);
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
return intersect.rect(bounds, point);
|
||||
};
|
||||
node.intersect = function (point) {
|
||||
return intersect.rect(node, point);
|
||||
};
|
||||
|
@@ -5,6 +5,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import intersect from '../intersect/index.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
function createLine(r: number) {
|
||||
const xAxis45 = Math.cos(Math.PI / 4); // cosine of 45 degrees
|
||||
@@ -57,6 +58,11 @@ export function crossedCircle<T extends SVGGraphicsElement>(parent: D3Selection<
|
||||
|
||||
updateNodeBounds(node, crossedCircle);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const radius = Math.max(30, bounds?.width ?? 0);
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('crossedCircle intersect', node, { radius, point });
|
||||
const pos = intersect.circle(node, radius, point);
|
||||
|
@@ -4,6 +4,7 @@ import type { Node } from '../../types.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
function generateCirclePoints(
|
||||
centerX: number,
|
||||
@@ -35,6 +36,21 @@ function generateCirclePoints(
|
||||
return points;
|
||||
}
|
||||
|
||||
function getRectPoints(w: number, h: number, radius: number) {
|
||||
return [
|
||||
{ x: w / 2, y: -h / 2 - radius },
|
||||
{ x: -w / 2, y: -h / 2 - radius },
|
||||
...generateCirclePoints(w / 2, -h / 2, radius, 20, -90, 0),
|
||||
{ x: -w / 2 - radius, y: -radius },
|
||||
...generateCirclePoints(w / 2 + w * 0.1, -radius, radius, 20, -180, -270),
|
||||
...generateCirclePoints(w / 2 + w * 0.1, radius, radius, 20, -90, -180),
|
||||
{ x: -w / 2 - radius, y: h / 2 },
|
||||
...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90),
|
||||
{ x: -w / 2, y: h / 2 + radius },
|
||||
{ x: w / 2, y: h / 2 + radius },
|
||||
];
|
||||
}
|
||||
|
||||
export async function curlyBraceLeft<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
node: Node
|
||||
@@ -57,18 +73,7 @@ export async function curlyBraceLeft<T extends SVGGraphicsElement>(
|
||||
...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90),
|
||||
];
|
||||
|
||||
const rectPoints = [
|
||||
{ x: w / 2, y: -h / 2 - radius },
|
||||
{ x: -w / 2, y: -h / 2 - radius },
|
||||
...generateCirclePoints(w / 2, -h / 2, radius, 20, -90, 0),
|
||||
{ x: -w / 2 - radius, y: -radius },
|
||||
...generateCirclePoints(w / 2 + w * 0.1, -radius, radius, 20, -180, -270),
|
||||
...generateCirclePoints(w / 2 + w * 0.1, radius, radius, 20, -90, -180),
|
||||
{ x: -w / 2 - radius, y: h / 2 },
|
||||
...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90),
|
||||
{ x: -w / 2, y: h / 2 + radius },
|
||||
{ x: w / 2, y: h / 2 + radius },
|
||||
];
|
||||
const rectPoints = getRectPoints(w, h, radius);
|
||||
|
||||
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||
const rc = rough.svg(shapeSvg);
|
||||
@@ -105,6 +110,15 @@ export async function curlyBraceLeft<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, curlyBraceLeftShape);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const w = bounds.width;
|
||||
const h = bounds.height;
|
||||
const radius = Math.max(5, h * 0.1);
|
||||
|
||||
const rectPoints = getRectPoints(w, h, radius);
|
||||
return intersect.polygon(bounds, rectPoints, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, rectPoints, point);
|
||||
|
||||
|
@@ -4,6 +4,7 @@ import type { Node } from '../../types.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
function generateCirclePoints(
|
||||
centerX: number,
|
||||
@@ -35,6 +36,21 @@ function generateCirclePoints(
|
||||
return points;
|
||||
}
|
||||
|
||||
function getRectPoints(w: number, h: number, radius: number) {
|
||||
return [
|
||||
{ x: -w / 2, y: -h / 2 - radius },
|
||||
{ x: w / 2, y: -h / 2 - radius },
|
||||
...generateCirclePoints(w / 2, -h / 2, radius, 20, -90, 0),
|
||||
{ x: w / 2 + radius, y: -radius },
|
||||
...generateCirclePoints(w / 2 + radius * 2, -radius, radius, 20, -180, -270),
|
||||
...generateCirclePoints(w / 2 + radius * 2, radius, radius, 20, -90, -180),
|
||||
{ x: w / 2 + radius, y: h / 2 },
|
||||
...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90),
|
||||
{ x: w / 2, y: h / 2 + radius },
|
||||
{ x: -w / 2, y: h / 2 + radius },
|
||||
];
|
||||
}
|
||||
|
||||
export async function curlyBraceRight<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
node: Node
|
||||
@@ -57,18 +73,7 @@ export async function curlyBraceRight<T extends SVGGraphicsElement>(
|
||||
...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90),
|
||||
];
|
||||
|
||||
const rectPoints = [
|
||||
{ x: -w / 2, y: -h / 2 - radius },
|
||||
{ x: w / 2, y: -h / 2 - radius },
|
||||
...generateCirclePoints(w / 2, -h / 2, radius, 20, -90, 0),
|
||||
{ x: w / 2 + radius, y: -radius },
|
||||
...generateCirclePoints(w / 2 + radius * 2, -radius, radius, 20, -180, -270),
|
||||
...generateCirclePoints(w / 2 + radius * 2, radius, radius, 20, -90, -180),
|
||||
{ x: w / 2 + radius, y: h / 2 },
|
||||
...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90),
|
||||
{ x: w / 2, y: h / 2 + radius },
|
||||
{ x: -w / 2, y: h / 2 + radius },
|
||||
];
|
||||
const rectPoints = getRectPoints(w, h, radius);
|
||||
|
||||
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||
const rc = rough.svg(shapeSvg);
|
||||
@@ -105,6 +110,15 @@ export async function curlyBraceRight<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, curlyBraceRightShape);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const w = bounds.width;
|
||||
const h = bounds.height;
|
||||
const radius = Math.max(5, h * 0.1);
|
||||
|
||||
const rectPoints = getRectPoints(w, h, radius);
|
||||
return intersect.polygon(bounds, rectPoints, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, rectPoints, point);
|
||||
|
||||
|
@@ -4,6 +4,7 @@ import type { Node } from '../../types.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
function generateCirclePoints(
|
||||
centerX: number,
|
||||
@@ -35,6 +36,25 @@ function generateCirclePoints(
|
||||
return points;
|
||||
}
|
||||
|
||||
const getRectPoints = (w: number, h: number, radius: number) => [
|
||||
{ x: w / 2, y: -h / 2 - radius },
|
||||
{ x: -w / 2, y: -h / 2 - radius },
|
||||
...generateCirclePoints(w / 2, -h / 2, radius, 20, -90, 0),
|
||||
{ x: -w / 2 - radius, y: -radius },
|
||||
...generateCirclePoints(w / 2 + radius * 2, -radius, radius, 20, -180, -270),
|
||||
...generateCirclePoints(w / 2 + radius * 2, radius, radius, 20, -90, -180),
|
||||
{ x: -w / 2 - radius, y: h / 2 },
|
||||
...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90),
|
||||
{ x: -w / 2, y: h / 2 + radius },
|
||||
{ x: w / 2 - radius - radius / 2, y: h / 2 + radius },
|
||||
...generateCirclePoints(-w / 2 + radius + radius / 2, -h / 2, radius, 20, -90, -180),
|
||||
{ x: w / 2 - radius / 2, y: radius },
|
||||
...generateCirclePoints(-w / 2 - radius / 2, -radius, radius, 20, 0, 90),
|
||||
...generateCirclePoints(-w / 2 - radius / 2, radius, radius, 20, -90, 0),
|
||||
{ x: w / 2 - radius / 2, y: -radius },
|
||||
...generateCirclePoints(-w / 2 + radius + radius / 2, h / 2, radius, 30, -180, -270),
|
||||
];
|
||||
|
||||
export async function curlyBraces<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
node: Node
|
||||
@@ -66,24 +86,7 @@ export async function curlyBraces<T extends SVGGraphicsElement>(
|
||||
...generateCirclePoints(-w / 2 + radius + radius / 2, h / 2, radius, 30, -180, -270),
|
||||
];
|
||||
|
||||
const rectPoints = [
|
||||
{ x: w / 2, y: -h / 2 - radius },
|
||||
{ x: -w / 2, y: -h / 2 - radius },
|
||||
...generateCirclePoints(w / 2, -h / 2, radius, 20, -90, 0),
|
||||
{ x: -w / 2 - radius, y: -radius },
|
||||
...generateCirclePoints(w / 2 + radius * 2, -radius, radius, 20, -180, -270),
|
||||
...generateCirclePoints(w / 2 + radius * 2, radius, radius, 20, -90, -180),
|
||||
{ x: -w / 2 - radius, y: h / 2 },
|
||||
...generateCirclePoints(w / 2, h / 2, radius, 20, 0, 90),
|
||||
{ x: -w / 2, y: h / 2 + radius },
|
||||
{ x: w / 2 - radius - radius / 2, y: h / 2 + radius },
|
||||
...generateCirclePoints(-w / 2 + radius + radius / 2, -h / 2, radius, 20, -90, -180),
|
||||
{ x: w / 2 - radius / 2, y: radius },
|
||||
...generateCirclePoints(-w / 2 - radius / 2, -radius, radius, 20, 0, 90),
|
||||
...generateCirclePoints(-w / 2 - radius / 2, radius, radius, 20, -90, 0),
|
||||
{ x: w / 2 - radius / 2, y: -radius },
|
||||
...generateCirclePoints(-w / 2 + radius + radius / 2, h / 2, radius, 30, -180, -270),
|
||||
];
|
||||
const rectPoints = getRectPoints(w, h, radius);
|
||||
|
||||
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||
const rc = rough.svg(shapeSvg);
|
||||
@@ -124,6 +127,15 @@ export async function curlyBraces<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, curlyBracesShape);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const w = bounds.width;
|
||||
const h = bounds.height;
|
||||
const radius = Math.max(5, h * 0.1);
|
||||
|
||||
const rectPoints = getRectPoints(w, h, radius);
|
||||
return intersect.polygon(bounds, rectPoints, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, rectPoints, point);
|
||||
|
||||
|
@@ -10,6 +10,16 @@ import type { Node } from '../../types.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
const getTrapezoidPoints = (rw: number, tw: number, totalHeight: number, radius: number) => [
|
||||
{ x: rw, y: 0 },
|
||||
{ x: tw, y: 0 },
|
||||
{ x: 0, y: totalHeight / 2 },
|
||||
{ x: tw, y: totalHeight },
|
||||
{ x: rw, y: totalHeight },
|
||||
...generateCirclePoints(-rw, -totalHeight / 2, radius, 50, 270, 90),
|
||||
];
|
||||
|
||||
export async function curvedTrapezoid<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -39,14 +49,7 @@ export async function curvedTrapezoid<T extends SVGGraphicsElement>(
|
||||
const rw = totalWidth - radius;
|
||||
const tw = totalHeight / 4;
|
||||
|
||||
const points = [
|
||||
{ x: rw, y: 0 },
|
||||
{ x: tw, y: 0 },
|
||||
{ x: 0, y: totalHeight / 2 },
|
||||
{ x: tw, y: totalHeight },
|
||||
{ x: rw, y: totalHeight },
|
||||
...generateCirclePoints(-rw, -totalHeight / 2, radius, 50, 270, 90),
|
||||
];
|
||||
const points = getTrapezoidPoints(rw, tw, totalHeight, radius);
|
||||
|
||||
const pathData = createPathFromPoints(points);
|
||||
const shapeNode = rc.path(pathData, options);
|
||||
@@ -66,6 +69,20 @@ export async function curvedTrapezoid<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, polygon);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const w = bounds.width;
|
||||
const h = bounds.height;
|
||||
const radius = h / 2;
|
||||
|
||||
const totalWidth = w,
|
||||
totalHeight = h;
|
||||
const rw = totalWidth - radius;
|
||||
const tw = totalHeight / 4;
|
||||
const points = getTrapezoidPoints(rw, tw, totalHeight, radius);
|
||||
|
||||
return intersect.polygon(bounds, points, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, points, point);
|
||||
return pos;
|
||||
|
@@ -5,6 +5,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import { handleUndefinedAttr } from '../../../utils.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export const createCylinderPathD = (
|
||||
x: number,
|
||||
@@ -96,22 +97,24 @@ export async function cylinder<T extends SVGGraphicsElement>(parent: D3Selection
|
||||
`translate(${-(bbox.width / 2) - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) + (node.padding ?? 0) / 1.5 - (bbox.y - (bbox.top ?? 0))})`
|
||||
);
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.rect(node, point);
|
||||
const x = pos.x - (node.x ?? 0);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const w = bounds.width;
|
||||
const rx = w / 2;
|
||||
const ry = rx / (2.5 + w / 50);
|
||||
const h = bounds.height;
|
||||
const pos = intersect.rect(bounds, point);
|
||||
const x = pos.x - (bounds.x ?? 0);
|
||||
if (
|
||||
rx != 0 &&
|
||||
(Math.abs(x) < (node.width ?? 0) / 2 ||
|
||||
(Math.abs(x) == (node.width ?? 0) / 2 &&
|
||||
Math.abs(pos.y - (node.y ?? 0)) > (node.height ?? 0) / 2 - ry))
|
||||
(Math.abs(x) < (w ?? 0) / 2 ||
|
||||
(Math.abs(x) == (w ?? 0) / 2 && Math.abs(pos.y - (bounds.y ?? 0)) > (h ?? 0) / 2 - ry))
|
||||
) {
|
||||
let y = ry * ry * (1 - (x * x) / (rx * rx));
|
||||
if (y > 0) {
|
||||
y = Math.sqrt(y);
|
||||
}
|
||||
y = ry - y;
|
||||
if (point.y - (node.y ?? 0) > 0) {
|
||||
if (point.y - (bounds.y ?? 0) > 0) {
|
||||
y = -y;
|
||||
}
|
||||
|
||||
@@ -121,5 +124,14 @@ export async function cylinder<T extends SVGGraphicsElement>(parent: D3Selection
|
||||
return pos;
|
||||
};
|
||||
|
||||
node.intersect = function (point: Point) {
|
||||
return this.calcIntersect
|
||||
? this.calcIntersect(
|
||||
{ x: node.x ?? 0, y: node.y ?? 0, width: node.width ?? 0, height: node.height ?? 0 },
|
||||
point
|
||||
)
|
||||
: { x: 0, y: 0 };
|
||||
};
|
||||
|
||||
return shapeSvg;
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ import type { Node } from '../../types.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function dividedRectangle<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -62,6 +63,10 @@ export async function dividedRectangle<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, polygon);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
return intersect.rect(bounds, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.rect(node, point);
|
||||
return pos;
|
||||
|
@@ -5,6 +5,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import { handleUndefinedAttr } from '../../../utils.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export const createCylinderPathD = (
|
||||
x: number,
|
||||
@@ -91,29 +92,36 @@ export async function cylinder<T extends SVGGraphicsElement>(parent: D3Selection
|
||||
|
||||
updateNodeBounds(node, cylinder);
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.rect(node, point);
|
||||
const x = pos.x - (node.x ?? 0);
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const pos = intersect.rect(bounds, point);
|
||||
const x = pos.x - (bounds.x ?? 0);
|
||||
|
||||
if (
|
||||
rx != 0 &&
|
||||
(Math.abs(x) < (node.width ?? 0) / 2 ||
|
||||
(Math.abs(x) == (node.width ?? 0) / 2 &&
|
||||
Math.abs(pos.y - (node.y ?? 0)) > (node.height ?? 0) / 2 - ry))
|
||||
(Math.abs(x) < (bounds.width ?? 0) / 2 ||
|
||||
(Math.abs(x) == (bounds.width ?? 0) / 2 &&
|
||||
Math.abs(pos.y - (bounds.y ?? 0)) > (bounds.height ?? 0) / 2 - ry))
|
||||
) {
|
||||
let y = ry * ry * (1 - (x * x) / (rx * rx));
|
||||
if (y != 0) {
|
||||
y = Math.sqrt(y);
|
||||
}
|
||||
y = ry - y;
|
||||
if (point.y - (node.y ?? 0) > 0) {
|
||||
if (point.y - (bounds.y ?? 0) > 0) {
|
||||
y = -y;
|
||||
}
|
||||
|
||||
pos.y += y;
|
||||
}
|
||||
};
|
||||
|
||||
return pos;
|
||||
node.intersect = function (point) {
|
||||
return this.calcIntersect
|
||||
? this.calcIntersect(
|
||||
{ x: node.x ?? 0, y: node.y ?? 0, width: node.width ?? 0, height: node.height ?? 0 },
|
||||
point
|
||||
)
|
||||
: { x: 0, y: 0 };
|
||||
};
|
||||
|
||||
return shapeSvg;
|
||||
|
@@ -6,6 +6,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import { handleUndefinedAttr } from '../../../utils.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function doublecircle<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -62,6 +63,11 @@ export async function doublecircle<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, circleGroup);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('DoubleCircle intersect', node, outerRadius, point);
|
||||
return intersect.circle(node, outerRadius, point);
|
||||
|
@@ -5,6 +5,7 @@ import intersect from '../intersect/index.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import { getNodeClasses, updateNodeBounds } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export function filledCircle<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -46,6 +47,11 @@ export function filledCircle<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, filledCircle);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('filledCircle intersect', node, { radius, point });
|
||||
const pos = intersect.circle(node, radius, point);
|
||||
|
@@ -6,6 +6,15 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import { createPathFromPoints } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
function getPoints(tw: number, h: number) {
|
||||
return [
|
||||
{ x: 0, y: -h },
|
||||
{ x: tw, y: -h },
|
||||
{ x: tw / 2, y: 0 },
|
||||
];
|
||||
}
|
||||
|
||||
export async function flippedTriangle<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -19,11 +28,7 @@ export async function flippedTriangle<T extends SVGGraphicsElement>(
|
||||
const h = w + bbox.height;
|
||||
|
||||
const tw = w + bbox.height;
|
||||
const points = [
|
||||
{ x: 0, y: -h },
|
||||
{ x: tw, y: -h },
|
||||
{ x: tw / 2, y: 0 },
|
||||
];
|
||||
const points = getPoints(tw, h);
|
||||
|
||||
const { cssStyles } = node;
|
||||
|
||||
@@ -59,6 +64,16 @@ export async function flippedTriangle<T extends SVGGraphicsElement>(
|
||||
`translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))}, ${-h / 2 + (node.padding ?? 0) / 2 + (bbox.y - (bbox.top ?? 0))})`
|
||||
);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const w = bounds.width;
|
||||
const h = bounds.height;
|
||||
|
||||
const tw = w + bounds.height;
|
||||
const points = getPoints(tw, h);
|
||||
return intersect.polygon(node, points, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('Triangle intersect', node, points, point);
|
||||
return intersect.polygon(node, points, point);
|
||||
|
@@ -4,6 +4,7 @@ import intersect from '../intersect/index.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import { getNodeClasses, updateNodeBounds } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export function forkJoin<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -59,6 +60,10 @@ export function forkJoin<T extends SVGGraphicsElement>(
|
||||
node.width += padding / 2 || 0;
|
||||
node.height += padding / 2 || 0;
|
||||
}
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
return intersect.rect(bounds, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.rect(node, point);
|
||||
};
|
||||
|
@@ -11,6 +11,7 @@ import type { Node } from '../../types.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function halfRoundedRectangle<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -63,6 +64,12 @@ export async function halfRoundedRectangle<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, polygon);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('Pill intersect', node, { radius, point });
|
||||
const pos = intersect.polygon(node, points, point);
|
||||
|
@@ -5,6 +5,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export const createHexagonPathD = (
|
||||
x: number,
|
||||
@@ -72,6 +73,12 @@ export async function hexagon<T extends SVGGraphicsElement>(parent: D3Selection<
|
||||
|
||||
updateNodeBounds(node, polygon);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.polygon(node, points, point);
|
||||
};
|
||||
|
@@ -5,6 +5,7 @@ import type { Node } from '../../types.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function hourglass<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles, nodeStyles } = styles2String(node);
|
||||
@@ -52,6 +53,18 @@ export async function hourglass<T extends SVGGraphicsElement>(parent: D3Selectio
|
||||
|
||||
// label.attr('transform', `translate(${-bbox.width / 2}, ${(h/2)})`); // To transform text below hourglass shape
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const { width: w, height: h } = bounds;
|
||||
const points = [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: w, y: 0 },
|
||||
{ x: 0, y: h },
|
||||
{ x: w, y: h },
|
||||
];
|
||||
const res = intersect.polygon(bounds, points, point);
|
||||
return { x: res.x - 0.5, y: res.y - 0.5 };
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('Pill intersect', node, { points });
|
||||
const pos = intersect.polygon(node, points, point);
|
||||
|
@@ -6,6 +6,7 @@ import intersect from '../intersect/index.js';
|
||||
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import { labelHelper, updateNodeBounds } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function icon<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -97,6 +98,12 @@ export async function icon<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, outerShape);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('iconSquare intersect', node, point);
|
||||
if (!node.label) {
|
||||
|
@@ -6,6 +6,7 @@ import intersect from '../intersect/index.js';
|
||||
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import { labelHelper, updateNodeBounds } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function iconCircle<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -94,6 +95,12 @@ export async function iconCircle<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, outerShape);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('iconSquare intersect', node, point);
|
||||
const pos = intersect.rect(node, point);
|
||||
|
@@ -7,6 +7,7 @@ import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShap
|
||||
import { createRoundedRectPathD } from './roundedRectPath.js';
|
||||
import { labelHelper, updateNodeBounds } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function iconRounded<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -104,6 +105,12 @@ export async function iconRounded<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, outerShape);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('iconSquare intersect', node, point);
|
||||
if (!node.label) {
|
||||
|
@@ -7,6 +7,7 @@ import { createRoundedRectPathD } from './roundedRectPath.js';
|
||||
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import { labelHelper, updateNodeBounds } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function iconSquare<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -104,6 +105,12 @@ export async function iconSquare<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, outerShape);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('iconSquare intersect', node, point);
|
||||
if (!node.label) {
|
||||
|
@@ -5,6 +5,7 @@ import intersect from '../intersect/index.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import { labelHelper, updateNodeBounds } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function imageSquare<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -108,6 +109,12 @@ export async function imageSquare<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, outerShape);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('iconSquare intersect', node, point);
|
||||
if (!node.label) {
|
||||
|
@@ -5,21 +5,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
|
||||
// export const createInvertedTrapezoidPathD = (
|
||||
// x: number,
|
||||
// y: number,
|
||||
// width: number,
|
||||
// height: number
|
||||
// ): string => {
|
||||
// return [
|
||||
// `M${x + height / 6},${y}`,
|
||||
// `L${x + width - height / 6},${y}`,
|
||||
// `L${x + width + (2 * height) / 6},${y - height}`,
|
||||
// `L${x - (2 * height) / 6},${y - height}`,
|
||||
// 'Z',
|
||||
// ].join(' ');
|
||||
// };
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function inv_trapezoid<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -70,6 +56,12 @@ export async function inv_trapezoid<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, polygon);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.polygon(node, points, point);
|
||||
};
|
||||
|
@@ -5,6 +5,7 @@ import { createRoundedRectPathD } from './roundedRectPath.js';
|
||||
import { userNodeOverrides, styles2String } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
const colorFromPriority = (priority: NonNullable<KanbanNode['priority']>) => {
|
||||
switch (priority) {
|
||||
@@ -155,6 +156,12 @@ export async function kanbanItem<T extends SVGGraphicsElement>(
|
||||
updateNodeBounds(kanbanNode, rect);
|
||||
kanbanNode.height = totalHeight;
|
||||
|
||||
kanbanNode.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
kanbanNode.intersect = function (point) {
|
||||
return intersect.rect(kanbanNode, point);
|
||||
};
|
||||
|
@@ -3,6 +3,7 @@ import { drawRect } from './drawRect.js';
|
||||
import { labelHelper, updateNodeBounds } from './util.js';
|
||||
import intersect from '../intersect/index.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function roundedRect<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -48,8 +49,12 @@ export async function labelRect<T extends SVGGraphicsElement>(parent: D3Selectio
|
||||
// }
|
||||
|
||||
updateNodeBounds(node, rect);
|
||||
// node.width = 1;
|
||||
// node.height = 1;
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.rect(node, point);
|
||||
|
@@ -5,6 +5,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function lean_left<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles, nodeStyles } = styles2String(node);
|
||||
@@ -50,6 +51,12 @@ export async function lean_left<T extends SVGGraphicsElement>(parent: D3Selectio
|
||||
|
||||
updateNodeBounds(node, polygon);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.polygon(node, points, point);
|
||||
};
|
||||
|
@@ -5,6 +5,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function lean_right<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles, nodeStyles } = styles2String(node);
|
||||
@@ -49,8 +50,59 @@ export async function lean_right<T extends SVGGraphicsElement>(parent: D3Selecti
|
||||
|
||||
updateNodeBounds(node, polygon);
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.polygon(node, points, point);
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const w = bounds.width;
|
||||
const h = bounds.height;
|
||||
const dx = h / 2;
|
||||
const z = w - h;
|
||||
// (w = dx+z+dx)
|
||||
const points = [
|
||||
{ x: -dx, y: 0 },
|
||||
{ x: z, y: 0 },
|
||||
{ x: z + dx, y: -h },
|
||||
{ x: 0, y: -h },
|
||||
];
|
||||
|
||||
const res = intersect.polygon(bounds, points, point);
|
||||
// if (node.id === 'C') {
|
||||
// console.log(
|
||||
// 'APA14!',
|
||||
// bounds.x,
|
||||
// bounds.x,
|
||||
// bounds.width,
|
||||
// '\nw:',
|
||||
// w,
|
||||
// points,
|
||||
// '\nExternal point: ',
|
||||
// '(',
|
||||
// point.x,
|
||||
// point.y,
|
||||
// ')\nIntersection:',
|
||||
// res
|
||||
// );
|
||||
// }
|
||||
return { x: res.x - 0.5, y: res.y - 0.5 };
|
||||
};
|
||||
|
||||
node.intersect = function (point: Point) {
|
||||
const res = intersect.polygon(node, points, point);
|
||||
// if (node.id === 'C') {
|
||||
// console.log(
|
||||
// 'APA14!!',
|
||||
// node.x,
|
||||
// node.y,
|
||||
// '\nw:',
|
||||
// node.width,
|
||||
// points,
|
||||
// '\nExternal point: ',
|
||||
// '(',
|
||||
// point.x,
|
||||
// point.y,
|
||||
// ')\nIntersection:',
|
||||
// res
|
||||
// );
|
||||
// }
|
||||
return res;
|
||||
};
|
||||
|
||||
return shapeSvg;
|
||||
|
@@ -6,7 +6,17 @@ import rough from 'roughjs';
|
||||
import intersect from '../intersect/index.js';
|
||||
import { createPathFromPoints } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
function getPoints(width: number, height: number, gapX: number, gapY: number) {
|
||||
return [
|
||||
{ x: width, y: 0 },
|
||||
{ x: 0, y: height / 2 + gapY / 2 },
|
||||
{ x: width - 4 * gapX, y: height / 2 + gapY / 2 },
|
||||
{ x: 0, y: height },
|
||||
{ x: width, y: height / 2 - gapY / 2 },
|
||||
{ x: 4 * gapX, y: height / 2 - gapY / 2 },
|
||||
];
|
||||
}
|
||||
export function lightningBolt<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles, nodeStyles } = styles2String(node);
|
||||
node.label = '';
|
||||
@@ -55,11 +65,21 @@ export function lightningBolt<T extends SVGGraphicsElement>(parent: D3Selection<
|
||||
|
||||
updateNodeBounds(node, lightningBolt);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const { width: w, height: h } = bounds;
|
||||
const gapX = Math.max(5, w * 0.1);
|
||||
const gapY = Math.max(5, h * 0.1);
|
||||
const p = getPoints(w, h, gapX, gapY);
|
||||
const res = intersect.polygon(bounds, p, point);
|
||||
|
||||
return { x: res.x - 0.5, y: res.y - 0.5 };
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('lightningBolt intersect', node, point);
|
||||
const pos = intersect.polygon(node, points, point);
|
||||
const res = intersect.polygon(node, points, point);
|
||||
|
||||
return pos;
|
||||
return res;
|
||||
};
|
||||
|
||||
return shapeSvg;
|
||||
|
@@ -5,6 +5,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import { handleUndefinedAttr } from '../../../utils.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export const createCylinderPathD = (
|
||||
x: number,
|
||||
@@ -110,6 +111,12 @@ export async function linedCylinder<T extends SVGGraphicsElement>(
|
||||
`translate(${-(bbox.width / 2) - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) + ry - (bbox.y - (bbox.top ?? 0))})`
|
||||
);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.rect(node, point);
|
||||
const x = pos.x - (node.x ?? 0);
|
||||
|
@@ -9,6 +9,7 @@ import type { Node } from '../../types.js';
|
||||
import rough from 'roughjs';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function linedWaveEdgedRect<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -74,6 +75,13 @@ export async function linedWaveEdgedRect<T extends SVGGraphicsElement>(
|
||||
);
|
||||
|
||||
updateNodeBounds(node, waveEdgeRect);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, points, point);
|
||||
return pos;
|
||||
|
@@ -4,6 +4,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import intersect from '../intersect/index.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function multiRect<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles, nodeStyles } = styles2String(node);
|
||||
@@ -74,6 +75,12 @@ export async function multiRect<T extends SVGGraphicsElement>(parent: D3Selectio
|
||||
|
||||
updateNodeBounds(node, multiRect);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, outerPathPoints, point);
|
||||
return pos;
|
||||
|
@@ -10,6 +10,7 @@ import type { Node } from '../../types.js';
|
||||
import rough from 'roughjs';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function multiWaveEdgedRectangle<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -99,6 +100,12 @@ export async function multiWaveEdgedRectangle<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, shape);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, outerPathPoints, point);
|
||||
return pos;
|
||||
|
@@ -5,6 +5,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import { getNodeClasses, labelHelper, updateNodeBounds } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import { getConfig } from '../../../config.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function note<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -52,6 +53,12 @@ export async function note<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, rect);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.rect(node, point);
|
||||
};
|
||||
|
@@ -92,9 +92,8 @@ export async function question<T extends SVGGraphicsElement>(parent: D3Selection
|
||||
return { x: res.x - 0.5, y: res.y - 0.5 }; // Adjusted result
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
// @ts-ignore TODO fix this (KNSV)
|
||||
return this.calcIntersect(node as Bounds, point);
|
||||
node.intersect = function (point: Point) {
|
||||
return this.calcIntersect ? this.calcIntersect(node as Bounds, point) : { x: 0, y: 0 };
|
||||
};
|
||||
|
||||
return shapeSvg;
|
||||
|
@@ -4,6 +4,7 @@ import type { Node } from '../../types.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function rect_left_inv_arrow<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -60,6 +61,12 @@ export async function rect_left_inv_arrow<T extends SVGGraphicsElement>(
|
||||
);
|
||||
updateNodeBounds(node, polygon);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.polygon(node, points, point);
|
||||
};
|
||||
|
@@ -10,6 +10,7 @@ import { getConfig } from '../../../diagram-api/diagramAPI.js';
|
||||
import { createRoundedRectPathD } from './roundedRectPath.js';
|
||||
import { log } from '../../../logger.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function rectWithTitle<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -150,6 +151,12 @@ export async function rectWithTitle<T extends SVGGraphicsElement>(
|
||||
}
|
||||
updateNodeBounds(node, rect);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.rect(node, point);
|
||||
};
|
||||
|
@@ -5,6 +5,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import { handleUndefinedAttr } from '../../../utils.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function shadedProcess<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -63,6 +64,12 @@ export async function shadedProcess<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, rect);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.rect(node, point);
|
||||
};
|
||||
|
@@ -4,6 +4,7 @@ import type { Node } from '../../types.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function slopedRect<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles, nodeStyles } = styles2String(node);
|
||||
@@ -54,6 +55,12 @@ export async function slopedRect<T extends SVGGraphicsElement>(parent: D3Selecti
|
||||
|
||||
updateNodeBounds(node, polygon);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, points, point);
|
||||
return pos;
|
||||
|
@@ -6,6 +6,7 @@ import rough from 'roughjs';
|
||||
import { createRoundedRectPathD } from './roundedRectPath.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import { handleUndefinedAttr } from '../../../utils.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export const createStadiumPathD = (
|
||||
x: number,
|
||||
@@ -88,6 +89,12 @@ export async function stadium<T extends SVGGraphicsElement>(parent: D3Selection<
|
||||
|
||||
updateNodeBounds(node, rect);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.rect(node, point);
|
||||
};
|
||||
|
@@ -4,6 +4,7 @@ import intersect from '../intersect/index.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import { updateNodeBounds } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export function stateEnd<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -54,6 +55,12 @@ export function stateEnd<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, circle);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.circle(node, 7, point);
|
||||
};
|
||||
|
@@ -4,6 +4,7 @@ import intersect from '../intersect/index.js';
|
||||
import { solidStateFill } from './handDrawnShapeStyles.js';
|
||||
import { updateNodeBounds } from './util.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export function stateStart<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -33,6 +34,12 @@ export function stateStart<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, circle);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.circle(node, 7, point);
|
||||
};
|
||||
|
@@ -6,6 +6,7 @@ import rough from 'roughjs';
|
||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import { handleUndefinedAttr } from '../../../utils.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export const createSubroutinePathD = (
|
||||
x: number,
|
||||
@@ -79,6 +80,12 @@ export async function subroutine<T extends SVGGraphicsElement>(parent: D3Selecti
|
||||
updateNodeBounds(node, el);
|
||||
}
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.polygon(node, points, point);
|
||||
};
|
||||
|
@@ -4,6 +4,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import intersect from '../intersect/index.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function taggedRect<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles, nodeStyles } = styles2String(node);
|
||||
@@ -60,6 +61,12 @@ export async function taggedRect<T extends SVGGraphicsElement>(parent: D3Selecti
|
||||
|
||||
updateNodeBounds(node, taggedRect);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, rectPoints, point);
|
||||
|
||||
|
@@ -10,6 +10,7 @@ import type { Node } from '../../types.js';
|
||||
import rough from 'roughjs';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function taggedWaveEdgedRectangle<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -96,6 +97,13 @@ export async function taggedWaveEdgedRectangle<T extends SVGGraphicsElement>(
|
||||
);
|
||||
|
||||
updateNodeBounds(node, waveEdgeRect);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, points, point);
|
||||
return pos;
|
||||
|
@@ -3,6 +3,7 @@ import intersect from '../intersect/index.js';
|
||||
import type { Node } from '../../types.js';
|
||||
import { styles2String } from './handDrawnShapeStyles.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function text<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles, nodeStyles } = styles2String(node);
|
||||
@@ -29,6 +30,12 @@ export async function text<T extends SVGGraphicsElement>(parent: D3Selection<T>,
|
||||
|
||||
updateNodeBounds(node, rect);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.rect(node, point);
|
||||
};
|
||||
|
@@ -5,6 +5,7 @@ import rough from 'roughjs';
|
||||
import intersect from '../intersect/index.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import { handleUndefinedAttr } from '../../../utils.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export const createCylinderPathD = (
|
||||
x: number,
|
||||
@@ -113,6 +114,12 @@ export async function tiltedCylinder<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, cylinder);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.rect(node, point);
|
||||
const y = pos.y - (node.y ?? 0);
|
||||
|
@@ -5,21 +5,7 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
|
||||
// export const createTrapezoidPathD = (
|
||||
// x: number,
|
||||
// y: number,
|
||||
// width: number,
|
||||
// height: number
|
||||
// ): string => {
|
||||
// return [
|
||||
// `M${x - (2 * height) / 6},${y}`,
|
||||
// `L${x + width + (2 * height) / 6},${y}`,
|
||||
// `L${x + width - height / 6},${y - height}`,
|
||||
// `L${x + height / 6},${y - height}`,
|
||||
// 'Z',
|
||||
// ].join(' ');
|
||||
// };
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function trapezoid<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles, nodeStyles } = styles2String(node);
|
||||
@@ -65,6 +51,12 @@ export async function trapezoid<T extends SVGGraphicsElement>(parent: D3Selectio
|
||||
|
||||
updateNodeBounds(node, polygon);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.polygon(node, points, point);
|
||||
};
|
||||
|
@@ -4,6 +4,7 @@ import type { Node } from '../../types.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function trapezoidalPentagon<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -52,6 +53,12 @@ export async function trapezoidalPentagon<T extends SVGGraphicsElement>(
|
||||
|
||||
updateNodeBounds(node, polygon);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, points, point);
|
||||
return pos;
|
||||
|
@@ -8,6 +8,7 @@ import { createPathFromPoints } from './util.js';
|
||||
import { evaluate } from '../../../diagrams/common/common.js';
|
||||
import { getConfig } from '../../../diagram-api/diagramAPI.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function triangle<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles, nodeStyles } = styles2String(node);
|
||||
@@ -59,6 +60,12 @@ export async function triangle<T extends SVGGraphicsElement>(parent: D3Selection
|
||||
`translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))}, ${h / 2 - (bbox.height + (node.padding ?? 0) / (useHtmlLabels ? 2 : 1) - (bbox.y - (bbox.top ?? 0)))})`
|
||||
);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
log.info('Triangle intersect', node, points, point);
|
||||
return intersect.polygon(node, points, point);
|
||||
|
@@ -10,6 +10,7 @@ import type { Node } from '../../types.js';
|
||||
import rough from 'roughjs';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
export async function waveEdgedRectangle<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
@@ -74,6 +75,13 @@ export async function waveEdgedRectangle<T extends SVGGraphicsElement>(
|
||||
);
|
||||
|
||||
updateNodeBounds(node, waveEdgeRect);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, points, point);
|
||||
return pos;
|
||||
|
@@ -10,7 +10,16 @@ import type { Node } from '../../types.js';
|
||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
function getPoints(w: number, finalH: number, waveAmplitude: number) {
|
||||
return [
|
||||
{ x: -w / 2, y: finalH / 2 },
|
||||
...generateFullSineWavePoints(-w / 2, finalH / 2, w / 2, finalH / 2, waveAmplitude, 1),
|
||||
{ x: w / 2, y: -finalH / 2 },
|
||||
...generateFullSineWavePoints(w / 2, -finalH / 2, -w / 2, -finalH / 2, waveAmplitude, -1),
|
||||
];
|
||||
}
|
||||
export async function waveRectangle<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
node: Node
|
||||
@@ -52,12 +61,7 @@ export async function waveRectangle<T extends SVGGraphicsElement>(
|
||||
options.fillStyle = 'solid';
|
||||
}
|
||||
|
||||
const points = [
|
||||
{ x: -w / 2, y: finalH / 2 },
|
||||
...generateFullSineWavePoints(-w / 2, finalH / 2, w / 2, finalH / 2, waveAmplitude, 1),
|
||||
{ x: w / 2, y: -finalH / 2 },
|
||||
...generateFullSineWavePoints(w / 2, -finalH / 2, -w / 2, -finalH / 2, waveAmplitude, -1),
|
||||
];
|
||||
const points = getPoints(w, finalH, waveAmplitude);
|
||||
|
||||
const waveRectPath = createPathFromPoints(points);
|
||||
const waveRectNode = rc.path(waveRectPath, options);
|
||||
@@ -75,6 +79,18 @@ export async function waveRectangle<T extends SVGGraphicsElement>(
|
||||
}
|
||||
|
||||
updateNodeBounds(node, waveRect);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const w = bounds.width;
|
||||
const h = bounds.height;
|
||||
|
||||
const waveAmplitude = Math.min(h * 0.2, h / 4);
|
||||
const finalH = h + waveAmplitude * 2;
|
||||
|
||||
const points = getPoints(w, finalH, waveAmplitude);
|
||||
return intersect.polygon(node, points, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, points, point);
|
||||
return pos;
|
||||
|
@@ -4,6 +4,16 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||
import rough from 'roughjs';
|
||||
import intersect from '../intersect/index.js';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
function getOutPathPoints(x: number, y: number, w: number, h: number, rectOffset: number) {
|
||||
return [
|
||||
{ x: x - rectOffset, y: y - rectOffset },
|
||||
{ x: x - rectOffset, y: y + h },
|
||||
{ x: x + w, y: y + h },
|
||||
{ x: x + w, y: y - rectOffset },
|
||||
];
|
||||
}
|
||||
|
||||
export async function windowPane<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||
const { labelStyles, nodeStyles } = styles2String(node);
|
||||
@@ -20,12 +30,7 @@ export async function windowPane<T extends SVGGraphicsElement>(parent: D3Selecti
|
||||
const rc = rough.svg(shapeSvg);
|
||||
const options = userNodeOverrides(node, {});
|
||||
|
||||
const outerPathPoints = [
|
||||
{ x: x - rectOffset, y: y - rectOffset },
|
||||
{ x: x - rectOffset, y: y + h },
|
||||
{ x: x + w, y: y + h },
|
||||
{ x: x + w, y: y - rectOffset },
|
||||
];
|
||||
const outerPathPoints = getOutPathPoints(x, y, w, h, rectOffset);
|
||||
|
||||
const path = `M${x - rectOffset},${y - rectOffset} L${x + w},${y - rectOffset} L${x + w},${y + h} L${x - rectOffset},${y + h} L${x - rectOffset},${y - rectOffset}
|
||||
M${x - rectOffset},${y} L${x + w},${y}
|
||||
@@ -58,6 +63,17 @@ export async function windowPane<T extends SVGGraphicsElement>(parent: D3Selecti
|
||||
|
||||
updateNodeBounds(node, windowPane);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
const w = bounds.width;
|
||||
const h = bounds.height;
|
||||
const rectOffset = 5;
|
||||
const x = -w / 2;
|
||||
const y = -h / 2;
|
||||
|
||||
const outerPathPoints = getOutPathPoints(x, y, w, h, rectOffset);
|
||||
return intersect.polygon(node, outerPathPoints, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
const pos = intersect.polygon(node, outerPathPoints, point);
|
||||
return pos;
|
||||
|
Reference in New Issue
Block a user