Diamond collision

This commit is contained in:
Mark Tolmacs 2025-05-14 18:32:05 +02:00
parent 14817c1b2d
commit bb4d9649a6
No known key found for this signature in database
3 changed files with 82 additions and 51 deletions

View File

@ -1,5 +1,7 @@
import { import {
curve, curve,
curveCatmullRomCubicApproxPoints,
curveOffsetPoints,
lineSegment, lineSegment,
pointFrom, pointFrom,
pointFromArray, pointFromArray,
@ -299,10 +301,10 @@ export function deconstructDiamondElement(
if (element.roundness?.type == null) { if (element.roundness?.type == null) {
const [top, right, bottom, left]: GlobalPoint[] = [ const [top, right, bottom, left]: GlobalPoint[] = [
pointFrom(element.x + topX, element.y + topY - offset), pointFrom(element.x + topX, element.y + topY),
pointFrom(element.x + rightX + offset, element.y + rightY), pointFrom(element.x + rightX, element.y + rightY),
pointFrom(element.x + bottomX, element.y + bottomY + offset), pointFrom(element.x + bottomX, element.y + bottomY),
pointFrom(element.x + leftX - offset, element.y + leftY), pointFrom(element.x + leftX, element.y + leftY),
]; ];
// Create the line segment parts of the diamond // Create the line segment parts of the diamond
@ -336,26 +338,26 @@ export function deconstructDiamondElement(
pointFrom(element.x + leftX, element.y + leftY), pointFrom(element.x + leftX, element.y + leftY),
]; ];
const offsets = [ const cornerPoints = [
vectorScale(vectorNormalize(vectorFromPoint(right, center)), offset), // RIGHT vectorScale(vectorNormalize(vectorFromPoint(right, center)), 0), // RIGHT
vectorScale(vectorNormalize(vectorFromPoint(bottom, center)), offset), // BOTTOM vectorScale(vectorNormalize(vectorFromPoint(bottom, center)), 0), // BOTTOM
vectorScale(vectorNormalize(vectorFromPoint(left, center)), offset), // LEFT vectorScale(vectorNormalize(vectorFromPoint(left, center)), 0), // LEFT
vectorScale(vectorNormalize(vectorFromPoint(top, center)), offset), // TOP vectorScale(vectorNormalize(vectorFromPoint(top, center)), 0), // TOP
]; ];
const corners = [ const baseCorners = [
curve( curve(
pointFromVector( pointFromVector(
offsets[0], cornerPoints[0],
pointFrom<GlobalPoint>( pointFrom<GlobalPoint>(
right[0] - verticalRadius, right[0] - verticalRadius,
right[1] - horizontalRadius, right[1] - horizontalRadius,
), ),
), ),
pointFromVector(offsets[0], right), pointFromVector(cornerPoints[0], right),
pointFromVector(offsets[0], right), pointFromVector(cornerPoints[0], right),
pointFromVector( pointFromVector(
offsets[0], cornerPoints[0],
pointFrom<GlobalPoint>( pointFrom<GlobalPoint>(
right[0] - verticalRadius, right[0] - verticalRadius,
right[1] + horizontalRadius, right[1] + horizontalRadius,
@ -364,16 +366,16 @@ export function deconstructDiamondElement(
), // RIGHT ), // RIGHT
curve( curve(
pointFromVector( pointFromVector(
offsets[1], cornerPoints[1],
pointFrom<GlobalPoint>( pointFrom<GlobalPoint>(
bottom[0] + verticalRadius, bottom[0] + verticalRadius,
bottom[1] - horizontalRadius, bottom[1] - horizontalRadius,
), ),
), ),
pointFromVector(offsets[1], bottom), pointFromVector(cornerPoints[1], bottom),
pointFromVector(offsets[1], bottom), pointFromVector(cornerPoints[1], bottom),
pointFromVector( pointFromVector(
offsets[1], cornerPoints[1],
pointFrom<GlobalPoint>( pointFrom<GlobalPoint>(
bottom[0] - verticalRadius, bottom[0] - verticalRadius,
bottom[1] - horizontalRadius, bottom[1] - horizontalRadius,
@ -382,16 +384,16 @@ export function deconstructDiamondElement(
), // BOTTOM ), // BOTTOM
curve( curve(
pointFromVector( pointFromVector(
offsets[2], cornerPoints[2],
pointFrom<GlobalPoint>( pointFrom<GlobalPoint>(
left[0] + verticalRadius, left[0] + verticalRadius,
left[1] + horizontalRadius, left[1] + horizontalRadius,
), ),
), ),
pointFromVector(offsets[2], left), pointFromVector(cornerPoints[2], left),
pointFromVector(offsets[2], left), pointFromVector(cornerPoints[2], left),
pointFromVector( pointFromVector(
offsets[2], cornerPoints[2],
pointFrom<GlobalPoint>( pointFrom<GlobalPoint>(
left[0] + verticalRadius, left[0] + verticalRadius,
left[1] - horizontalRadius, left[1] - horizontalRadius,
@ -400,16 +402,16 @@ export function deconstructDiamondElement(
), // LEFT ), // LEFT
curve( curve(
pointFromVector( pointFromVector(
offsets[3], cornerPoints[3],
pointFrom<GlobalPoint>( pointFrom<GlobalPoint>(
top[0] - verticalRadius, top[0] - verticalRadius,
top[1] + horizontalRadius, top[1] + horizontalRadius,
), ),
), ),
pointFromVector(offsets[3], top), pointFromVector(cornerPoints[3], top),
pointFromVector(offsets[3], top), pointFromVector(cornerPoints[3], top),
pointFromVector( pointFromVector(
offsets[3], cornerPoints[3],
pointFrom<GlobalPoint>( pointFrom<GlobalPoint>(
top[0] + verticalRadius, top[0] + verticalRadius,
top[1] + horizontalRadius, top[1] + horizontalRadius,
@ -418,12 +420,39 @@ export function deconstructDiamondElement(
), // TOP ), // TOP
]; ];
const corners =
offset > 0
? baseCorners.map(
(corner) =>
curveCatmullRomCubicApproxPoints(
curveOffsetPoints(corner, offset),
)!,
)
: [
[baseCorners[0]],
[baseCorners[1]],
[baseCorners[2]],
[baseCorners[3]],
];
const sides = [ const sides = [
lineSegment<GlobalPoint>(corners[0][3], corners[1][0]), lineSegment<GlobalPoint>(
lineSegment<GlobalPoint>(corners[1][3], corners[2][0]), corners[0][corners[0].length - 1][3],
lineSegment<GlobalPoint>(corners[2][3], corners[3][0]), corners[1][0][0],
lineSegment<GlobalPoint>(corners[3][3], corners[0][0]), ),
lineSegment<GlobalPoint>(
corners[1][corners[1].length - 1][3],
corners[2][0][0],
),
lineSegment<GlobalPoint>(
corners[2][corners[2].length - 1][3],
corners[3][0][0],
),
lineSegment<GlobalPoint>(
corners[3][corners[3].length - 1][3],
corners[0][0][0],
),
]; ];
return [sides, corners]; return [sides, corners.flat()];
} }

View File

@ -345,13 +345,13 @@ export const drawHighlightForDiamondWithRotation = (
topApprox[topApprox.length - 1][0], topApprox[topApprox.length - 1][0],
topApprox[topApprox.length - 1][1], topApprox[topApprox.length - 1][1],
); );
context.lineTo(rightApprox[0][0], rightApprox[0][1]); context.lineTo(rightApprox[1][0], rightApprox[1][1]);
drawCatmullRomCubicApprox(context, rightApprox); drawCatmullRomCubicApprox(context, rightApprox);
context.lineTo(bottomApprox[0][0], bottomApprox[0][1]); context.lineTo(bottomApprox[1][0], bottomApprox[1][1]);
drawCatmullRomCubicApprox(context, bottomApprox); drawCatmullRomCubicApprox(context, bottomApprox);
context.lineTo(leftApprox[0][0], leftApprox[0][1]); context.lineTo(leftApprox[1][0], leftApprox[1][1]);
drawCatmullRomCubicApprox(context, leftApprox); drawCatmullRomCubicApprox(context, leftApprox);
context.lineTo(topApprox[0][0], topApprox[0][1]); context.lineTo(topApprox[1][0], topApprox[1][1]);
drawCatmullRomCubicApprox(context, topApprox); drawCatmullRomCubicApprox(context, topApprox);
} }
@ -408,13 +408,13 @@ export const drawHighlightForDiamondWithRotation = (
topApprox[topApprox.length - 1][0], topApprox[topApprox.length - 1][0],
topApprox[topApprox.length - 1][1], topApprox[topApprox.length - 1][1],
); );
context.lineTo(leftApprox[0][0], leftApprox[0][1]); context.lineTo(leftApprox[1][0], leftApprox[1][1]);
drawCatmullRomCubicApprox(context, leftApprox); drawCatmullRomCubicApprox(context, leftApprox);
context.lineTo(bottomApprox[0][0], bottomApprox[0][1]); context.lineTo(bottomApprox[1][0], bottomApprox[1][1]);
drawCatmullRomCubicApprox(context, bottomApprox); drawCatmullRomCubicApprox(context, bottomApprox);
context.lineTo(rightApprox[0][0], rightApprox[0][1]); context.lineTo(rightApprox[1][0], rightApprox[1][1]);
drawCatmullRomCubicApprox(context, rightApprox); drawCatmullRomCubicApprox(context, rightApprox);
context.lineTo(topApprox[0][0], topApprox[0][1]); context.lineTo(topApprox[1][0], topApprox[1][1]);
drawCatmullRomCubicApprox(context, topApprox); drawCatmullRomCubicApprox(context, topApprox);
} }
context.closePath(); context.closePath();

View File

@ -329,15 +329,14 @@ export function curveCatmullRomQuadraticApproxPoints(
return pointSets; return pointSets;
} }
export function curveCatmullRomCubicApproxPoints( export function curveCatmullRomCubicApproxPoints<
points: GlobalPoint[], Point extends GlobalPoint | LocalPoint,
tension = 0.5, >(points: Point[], tension = 0.5) {
) {
if (points.length < 2) { if (points.length < 2) {
return; return;
} }
const pointSets: [GlobalPoint, GlobalPoint, GlobalPoint][] = []; const pointSets: Curve<Point>[] = [];
for (let i = 0; i < points.length - 1; i++) { for (let i = 0; i < points.length - 1; i++) {
const p0 = points[i - 1 < 0 ? 0 : i - 1]; const p0 = points[i - 1 < 0 ? 0 : i - 1];
const p1 = points[i]; const p1 = points[i];
@ -350,11 +349,14 @@ export function curveCatmullRomCubicApproxPoints(
const cp2x = p2[0] - tangent2[0] / 3; const cp2x = p2[0] - tangent2[0] / 3;
const cp2y = p2[1] - tangent2[1] / 3; const cp2y = p2[1] - tangent2[1] / 3;
pointSets.push([ pointSets.push(
pointFrom<GlobalPoint>(cp1x, cp1y), curve(
pointFrom<GlobalPoint>(cp2x, cp2y), pointFrom(p1[0], p1[1]),
pointFrom<GlobalPoint>(p2[0], p2[1]), pointFrom(cp1x, cp1y),
]); pointFrom(cp2x, cp2y),
pointFrom(p2[0], p2[1]),
),
);
} }
return pointSets; return pointSets;
@ -362,7 +364,7 @@ export function curveCatmullRomCubicApproxPoints(
export function curveOffsetPoints( export function curveOffsetPoints(
[p0, p1, p2, p3]: Curve<GlobalPoint>, [p0, p1, p2, p3]: Curve<GlobalPoint>,
offsetDist: number, offset: number,
steps = 50, steps = 50,
) { ) {
const offsetPoints = []; const offsetPoints = [];
@ -374,7 +376,7 @@ export function curveOffsetPoints(
const tangent = vectorNormalize(curveTangent(c, t)); const tangent = vectorNormalize(curveTangent(c, t));
const normal = vectorNormal(tangent); const normal = vectorNormal(tangent);
offsetPoints.push(pointFromVector(vectorScale(normal, offsetDist), point)); offsetPoints.push(pointFromVector(vectorScale(normal, offset), point));
} }
return offsetPoints; return offsetPoints;