#6097 Next batch of shapes

This commit is contained in:
Knut Sveidqvist
2024-11-30 13:42:50 +01:00
parent 0c28593ea5
commit 3c93e4640a
13 changed files with 141 additions and 156 deletions

View File

@@ -71,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;
@@ -85,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);
@@ -126,13 +128,7 @@ export async function bowTieRect<T extends SVGGraphicsElement>(parent: D3Selecti
const ry = h / 2;
const rx = ry / (2.5 + h / 50);
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);
return intersect.polygon(bounds, points, point);
};
node.intersect = function (point) {

View File

@@ -8,6 +8,20 @@ import { createPathFromPoints } from './util.js';
import type { D3Selection } from '../../../types.js';
import type { Bounds, Point } from '../../../types.js';
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;
@@ -16,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;
@@ -60,18 +64,8 @@ export async function card<T extends SVGGraphicsElement>(parent: D3Selection<T>,
const h = bounds.height;
const padding = 12;
const w = bounds.width;
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);
return intersect.polygon(bounds, points, point);
};

View File

@@ -5,7 +5,14 @@ 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 = '';
@@ -17,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);
@@ -51,12 +53,7 @@ export function choice<T extends SVGGraphicsElement>(parent: D3Selection<T>, nod
node.calcIntersect = function (bounds: Bounds, point: Point) {
const s = Math.max(28, bounds.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);
return intersect.circle(bounds, points, point);
};

View File

@@ -36,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
@@ -58,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);
@@ -111,18 +115,7 @@ export async function curlyBraceLeft<T extends SVGGraphicsElement>(
const h = bounds.height;
const radius = Math.max(5, h * 0.1);
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);
return intersect.polygon(bounds, rectPoints, point);
};

View File

@@ -36,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
@@ -58,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);
@@ -111,18 +115,7 @@ export async function curlyBraceRight<T extends SVGGraphicsElement>(
const h = bounds.height;
const radius = Math.max(5, h * 0.1);
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);
return intersect.polygon(bounds, rectPoints, point);
};

View File

@@ -98,27 +98,23 @@ export async function cylinder<T extends SVGGraphicsElement>(parent: D3Selection
);
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);
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;
}
@@ -128,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;
}

View File

@@ -64,9 +64,7 @@ export async function dividedRectangle<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);
return intersect.rect(bounds, point);
};
node.intersect = function (point) {

View File

@@ -93,34 +93,35 @@ export async function cylinder<T extends SVGGraphicsElement>(parent: D3Selection
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 x = pos.x - (node.x ?? 0);
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;

View File

@@ -64,7 +64,6 @@ export async function doublecircle<T extends SVGGraphicsElement>(
updateNodeBounds(node, circleGroup);
node.calcIntersect = function (bounds: Bounds, point: Point) {
// TODO: Implement intersect for this shape
const radius = bounds.width / 2;
return intersect.circle(bounds, radius, point);
};

View File

@@ -48,7 +48,6 @@ export function filledCircle<T extends SVGGraphicsElement>(
updateNodeBounds(node, filledCircle);
node.calcIntersect = function (bounds: Bounds, point: Point) {
// TODO: Implement intersect for this shape
const radius = bounds.width / 2;
return intersect.circle(bounds, radius, point);
};

View File

@@ -8,6 +8,14 @@ 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>,
node: Node
@@ -20,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;
@@ -62,8 +66,12 @@ export async function flippedTriangle<T extends SVGGraphicsElement>(
node.calcIntersect = function (bounds: Bounds, point: Point) {
// TODO: Implement intersect for this shape
const radius = bounds.width / 2;
return intersect.circle(bounds, radius, point);
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) {

View File

@@ -92,15 +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.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) {
// @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;

View File

@@ -6,6 +6,15 @@ 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);
node.labelStyle = labelStyles;
@@ -21,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}
@@ -60,9 +64,14 @@ export async function windowPane<T extends SVGGraphicsElement>(parent: D3Selecti
updateNodeBounds(node, windowPane);
node.calcIntersect = function (bounds: Bounds, point: Point) {
// TODO: Implement intersect for this shape
const radius = bounds.width / 2;
return intersect.circle(bounds, radius, 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) {