mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Precise rectanguloid when rounded
This commit is contained in:
parent
7275263686
commit
436a0568fa
2 changed files with 212 additions and 165 deletions
|
@ -21,6 +21,7 @@ import {
|
||||||
vectorNormal,
|
vectorNormal,
|
||||||
vectorScale,
|
vectorScale,
|
||||||
pointFromVector,
|
pointFromVector,
|
||||||
|
vector,
|
||||||
} from "@excalidraw/math";
|
} from "@excalidraw/math";
|
||||||
|
|
||||||
import { getCurvePathOps } from "@excalidraw/utils/shape";
|
import { getCurvePathOps } from "@excalidraw/utils/shape";
|
||||||
|
@ -1154,7 +1155,7 @@ export const doBoundsIntersect = (
|
||||||
return minX1 < maxX2 && maxX1 > minX2 && minY1 < maxY2 && maxY1 > minY2;
|
return minX1 < maxX2 && maxX1 > minX2 && minY1 < maxY2 && maxY1 > minY2;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function offsetBezier(
|
export function offsetCubicBezier(
|
||||||
p0: GlobalPoint,
|
p0: GlobalPoint,
|
||||||
p1: GlobalPoint,
|
p1: GlobalPoint,
|
||||||
p2: GlobalPoint,
|
p2: GlobalPoint,
|
||||||
|
@ -1176,3 +1177,30 @@ export function offsetBezier(
|
||||||
|
|
||||||
return offsetPoints;
|
return offsetPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function offsetQuadraticBezier(
|
||||||
|
p0: GlobalPoint,
|
||||||
|
p1: GlobalPoint,
|
||||||
|
p2: GlobalPoint,
|
||||||
|
offsetDist: number,
|
||||||
|
steps = 20,
|
||||||
|
) {
|
||||||
|
const offsetPoints = [];
|
||||||
|
|
||||||
|
for (let i = 0; i <= steps; i++) {
|
||||||
|
const t = i / steps;
|
||||||
|
const t1 = 1 - t;
|
||||||
|
const point = pointFrom<GlobalPoint>(
|
||||||
|
t1 * t1 * p0[0] + 2 * t1 * t * p1[0] + t * t * p2[0],
|
||||||
|
t1 * t1 * p0[1] + 2 * t1 * t * p1[1] + t * t * p2[1],
|
||||||
|
);
|
||||||
|
const tangentX = 2 * (1 - t) * (p1[0] - p0[0]) + 2 * t * (p2[0] - p1[0]);
|
||||||
|
const tangentY = 2 * (1 - t) * (p1[1] - p0[1]) + 2 * t * (p2[1] - p1[1]);
|
||||||
|
const tangent = vectorNormalize(vector(tangentX, tangentY));
|
||||||
|
const normal = vectorNormal(tangent);
|
||||||
|
|
||||||
|
offsetPoints.push(pointFromVector(vectorScale(normal, offsetDist), point));
|
||||||
|
}
|
||||||
|
|
||||||
|
return offsetPoints;
|
||||||
|
}
|
||||||
|
|
|
@ -51,7 +51,8 @@ import {
|
||||||
getCommonBounds,
|
getCommonBounds,
|
||||||
getDiamondPoints,
|
getDiamondPoints,
|
||||||
getElementAbsoluteCoords,
|
getElementAbsoluteCoords,
|
||||||
offsetBezier,
|
offsetCubicBezier,
|
||||||
|
offsetQuadraticBezier,
|
||||||
} from "@excalidraw/element/bounds";
|
} from "@excalidraw/element/bounds";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
@ -187,157 +188,149 @@ const drawHighlightForRectWithRotation = (
|
||||||
|
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
|
|
||||||
// {
|
{
|
||||||
// const topLeftApprox = offsetBezier(
|
const topLeftApprox = offsetQuadraticBezier(
|
||||||
// pointFrom(0, 0 + radius),
|
pointFrom(0, 0 + radius),
|
||||||
// pointFrom(0, 0),
|
pointFrom(0, 0),
|
||||||
// pointFrom(0, 0),
|
pointFrom(0 + radius, 0),
|
||||||
// pointFrom(0 + radius, 0),
|
padding,
|
||||||
// padding,
|
);
|
||||||
// );
|
const topRightApprox = offsetQuadraticBezier(
|
||||||
// const topRightApprox = offsetBezier(
|
pointFrom(element.width - radius, 0),
|
||||||
// pointFrom(element.width - radius, 0),
|
pointFrom(element.width, 0),
|
||||||
// pointFrom(element.width, 0),
|
pointFrom(element.width, radius),
|
||||||
// pointFrom(element.width, 0),
|
padding,
|
||||||
// pointFrom(element.width, radius),
|
);
|
||||||
// padding,
|
const bottomRightApprox = offsetQuadraticBezier(
|
||||||
// );
|
pointFrom(element.width, element.height - radius),
|
||||||
// const bottomRightApprox = offsetBezier(
|
pointFrom(element.width, element.height),
|
||||||
// pointFrom(element.width, element.height - radius),
|
pointFrom(element.width - radius, element.height),
|
||||||
// pointFrom(element.width, element.height),
|
padding,
|
||||||
// pointFrom(element.width, element.height),
|
);
|
||||||
// pointFrom(element.width - radius, element.height),
|
const bottomLeftApprox = offsetQuadraticBezier(
|
||||||
// padding,
|
pointFrom(radius, element.height),
|
||||||
// );
|
pointFrom(0, element.height),
|
||||||
// const bottomLeftApprox = offsetBezier(
|
pointFrom(0, element.height - radius),
|
||||||
// pointFrom(radius, element.height),
|
padding,
|
||||||
// pointFrom(0, element.height),
|
);
|
||||||
// pointFrom(0, element.height),
|
|
||||||
// pointFrom(0, element.height - radius),
|
|
||||||
// padding,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// context.moveTo(
|
context.moveTo(
|
||||||
// topLeftApprox[topLeftApprox.length - 1][0],
|
topLeftApprox[topLeftApprox.length - 1][0],
|
||||||
// topLeftApprox[topLeftApprox.length - 1][1],
|
topLeftApprox[topLeftApprox.length - 1][1],
|
||||||
|
);
|
||||||
|
context.lineTo(topRightApprox[0][0], topRightApprox[0][1]);
|
||||||
|
drawCatmullRomQuadraticApprox(context, topRightApprox);
|
||||||
|
context.lineTo(bottomRightApprox[0][0], bottomRightApprox[0][1]);
|
||||||
|
drawCatmullRomQuadraticApprox(context, bottomRightApprox);
|
||||||
|
context.lineTo(bottomLeftApprox[0][0], bottomLeftApprox[0][1]);
|
||||||
|
drawCatmullRomQuadraticApprox(context, bottomLeftApprox);
|
||||||
|
context.lineTo(topLeftApprox[0][0], topLeftApprox[0][1]);
|
||||||
|
drawCatmullRomQuadraticApprox(context, topLeftApprox);
|
||||||
|
}
|
||||||
|
|
||||||
|
// context.moveTo(-padding + radius, -padding);
|
||||||
|
// context.lineTo(element.width + padding - radius, -padding);
|
||||||
|
// context.quadraticCurveTo(
|
||||||
|
// element.width + padding,
|
||||||
|
// -padding,
|
||||||
|
// element.width + padding,
|
||||||
|
// -padding + radius,
|
||||||
// );
|
// );
|
||||||
// context.lineTo(topRightApprox[0][0], topRightApprox[0][1]);
|
// context.lineTo(element.width + padding, element.height + padding - radius);
|
||||||
// drawCatmullRom(context, topRightApprox);
|
// context.quadraticCurveTo(
|
||||||
// context.lineTo(bottomRightApprox[0][0], bottomRightApprox[0][1]);
|
// element.width + padding,
|
||||||
// drawCatmullRom(context, bottomRightApprox);
|
// element.height + padding,
|
||||||
// context.lineTo(bottomLeftApprox[0][0], bottomLeftApprox[0][1]);
|
// element.width + padding - radius,
|
||||||
// drawCatmullRom(context, bottomLeftApprox);
|
// element.height + padding,
|
||||||
// context.lineTo(topLeftApprox[0][0], topLeftApprox[0][1]);
|
// );
|
||||||
// drawCatmullRom(context, topLeftApprox);
|
// context.lineTo(-padding + radius, element.height + padding);
|
||||||
// }
|
// context.quadraticCurveTo(
|
||||||
|
// -padding,
|
||||||
|
// element.height + padding,
|
||||||
|
// -padding,
|
||||||
|
// element.height + padding - radius,
|
||||||
|
// );
|
||||||
|
// context.lineTo(-padding, -padding + radius);
|
||||||
|
// context.quadraticCurveTo(-padding, -padding, -padding + radius, -padding);
|
||||||
|
|
||||||
context.moveTo(-padding + radius, -padding);
|
// context.moveTo(-FIXED_BINDING_DISTANCE + radius, -FIXED_BINDING_DISTANCE);
|
||||||
context.lineTo(element.width + padding - radius, -padding);
|
// context.quadraticCurveTo(
|
||||||
context.quadraticCurveTo(
|
// -FIXED_BINDING_DISTANCE,
|
||||||
element.width + padding,
|
// -FIXED_BINDING_DISTANCE,
|
||||||
-padding,
|
// -FIXED_BINDING_DISTANCE,
|
||||||
element.width + padding,
|
// -FIXED_BINDING_DISTANCE + radius,
|
||||||
-padding + radius,
|
// );
|
||||||
);
|
// context.lineTo(
|
||||||
context.lineTo(element.width + padding, element.height + padding - radius);
|
// -FIXED_BINDING_DISTANCE,
|
||||||
context.quadraticCurveTo(
|
// element.height + FIXED_BINDING_DISTANCE - radius,
|
||||||
element.width + padding,
|
// );
|
||||||
element.height + padding,
|
// context.quadraticCurveTo(
|
||||||
element.width + padding - radius,
|
// -FIXED_BINDING_DISTANCE,
|
||||||
element.height + padding,
|
// element.height + FIXED_BINDING_DISTANCE,
|
||||||
);
|
// -FIXED_BINDING_DISTANCE + radius,
|
||||||
context.lineTo(-padding + radius, element.height + padding);
|
// element.height + FIXED_BINDING_DISTANCE,
|
||||||
context.quadraticCurveTo(
|
// );
|
||||||
-padding,
|
// context.lineTo(
|
||||||
element.height + padding,
|
// element.width + FIXED_BINDING_DISTANCE - radius,
|
||||||
-padding,
|
// element.height + FIXED_BINDING_DISTANCE,
|
||||||
element.height + padding - radius,
|
// );
|
||||||
);
|
// context.quadraticCurveTo(
|
||||||
context.lineTo(-padding, -padding + radius);
|
// element.width + FIXED_BINDING_DISTANCE,
|
||||||
context.quadraticCurveTo(-padding, -padding, -padding + radius, -padding);
|
// element.height + FIXED_BINDING_DISTANCE,
|
||||||
|
// element.width + FIXED_BINDING_DISTANCE,
|
||||||
context.moveTo(-FIXED_BINDING_DISTANCE + radius, -FIXED_BINDING_DISTANCE);
|
// element.height + FIXED_BINDING_DISTANCE - radius,
|
||||||
context.quadraticCurveTo(
|
// );
|
||||||
-FIXED_BINDING_DISTANCE,
|
// context.lineTo(
|
||||||
-FIXED_BINDING_DISTANCE,
|
// element.width + FIXED_BINDING_DISTANCE,
|
||||||
-FIXED_BINDING_DISTANCE,
|
// -FIXED_BINDING_DISTANCE + radius,
|
||||||
-FIXED_BINDING_DISTANCE + radius,
|
// );
|
||||||
);
|
// context.quadraticCurveTo(
|
||||||
context.lineTo(
|
// element.width + FIXED_BINDING_DISTANCE,
|
||||||
-FIXED_BINDING_DISTANCE,
|
// -FIXED_BINDING_DISTANCE,
|
||||||
element.height + FIXED_BINDING_DISTANCE - radius,
|
// element.width + FIXED_BINDING_DISTANCE - radius,
|
||||||
);
|
|
||||||
context.quadraticCurveTo(
|
|
||||||
-FIXED_BINDING_DISTANCE,
|
|
||||||
element.height + FIXED_BINDING_DISTANCE,
|
|
||||||
-FIXED_BINDING_DISTANCE + radius,
|
|
||||||
element.height + FIXED_BINDING_DISTANCE,
|
|
||||||
);
|
|
||||||
context.lineTo(
|
|
||||||
element.width + FIXED_BINDING_DISTANCE - radius,
|
|
||||||
element.height + FIXED_BINDING_DISTANCE,
|
|
||||||
);
|
|
||||||
context.quadraticCurveTo(
|
|
||||||
element.width + FIXED_BINDING_DISTANCE,
|
|
||||||
element.height + FIXED_BINDING_DISTANCE,
|
|
||||||
element.width + FIXED_BINDING_DISTANCE,
|
|
||||||
element.height + FIXED_BINDING_DISTANCE - radius,
|
|
||||||
);
|
|
||||||
context.lineTo(
|
|
||||||
element.width + FIXED_BINDING_DISTANCE,
|
|
||||||
-FIXED_BINDING_DISTANCE + radius,
|
|
||||||
);
|
|
||||||
context.quadraticCurveTo(
|
|
||||||
element.width + FIXED_BINDING_DISTANCE,
|
|
||||||
-FIXED_BINDING_DISTANCE,
|
|
||||||
element.width + FIXED_BINDING_DISTANCE - radius,
|
|
||||||
-FIXED_BINDING_DISTANCE,
|
|
||||||
);
|
|
||||||
context.lineTo(-FIXED_BINDING_DISTANCE + radius, -FIXED_BINDING_DISTANCE);
|
|
||||||
|
|
||||||
// {
|
|
||||||
// const topLeftApprox = offsetBezier(
|
|
||||||
// pointFrom(0 + radius, 0),
|
|
||||||
// pointFrom(0, 0),
|
|
||||||
// pointFrom(0, 0),
|
|
||||||
// pointFrom(0, 0 + radius),
|
|
||||||
// -FIXED_BINDING_DISTANCE,
|
|
||||||
// );
|
|
||||||
// const topRightApprox = offsetBezier(
|
|
||||||
// pointFrom(element.width, radius),
|
|
||||||
// pointFrom(element.width, 0),
|
|
||||||
// pointFrom(element.width, 0),
|
|
||||||
// pointFrom(element.width - radius, 0),
|
|
||||||
// -FIXED_BINDING_DISTANCE,
|
|
||||||
// );
|
|
||||||
// const bottomRightApprox = offsetBezier(
|
|
||||||
// pointFrom(element.width - radius, element.height),
|
|
||||||
// pointFrom(element.width, element.height),
|
|
||||||
// pointFrom(element.width, element.height),
|
|
||||||
// pointFrom(element.width, element.height - radius),
|
|
||||||
// -FIXED_BINDING_DISTANCE,
|
|
||||||
// );
|
|
||||||
// const bottomLeftApprox = offsetBezier(
|
|
||||||
// pointFrom(0, element.height - radius),
|
|
||||||
// pointFrom(0, element.height),
|
|
||||||
// pointFrom(0, element.height),
|
|
||||||
// pointFrom(radius, element.height),
|
|
||||||
// -FIXED_BINDING_DISTANCE,
|
// -FIXED_BINDING_DISTANCE,
|
||||||
// );
|
// );
|
||||||
|
// context.lineTo(-FIXED_BINDING_DISTANCE + radius, -FIXED_BINDING_DISTANCE);
|
||||||
|
|
||||||
// context.moveTo(
|
{
|
||||||
// topLeftApprox[topLeftApprox.length - 1][0],
|
const topLeftApprox = offsetQuadraticBezier(
|
||||||
// topLeftApprox[topLeftApprox.length - 1][1],
|
pointFrom(0 + radius, 0),
|
||||||
// );
|
pointFrom(0, 0),
|
||||||
// context.lineTo(bottomLeftApprox[0][0], bottomLeftApprox[0][1]);
|
pointFrom(0, 0 + radius),
|
||||||
// drawCatmullRom(context, bottomLeftApprox);
|
-FIXED_BINDING_DISTANCE,
|
||||||
// context.lineTo(bottomRightApprox[0][0], bottomRightApprox[0][1]);
|
);
|
||||||
// drawCatmullRom(context, bottomRightApprox);
|
const topRightApprox = offsetQuadraticBezier(
|
||||||
// context.lineTo(topRightApprox[0][0], topRightApprox[0][1]);
|
pointFrom(element.width, radius),
|
||||||
// drawCatmullRom(context, topRightApprox);
|
pointFrom(element.width, 0),
|
||||||
// context.lineTo(topLeftApprox[0][0], topLeftApprox[0][1]);
|
pointFrom(element.width - radius, 0),
|
||||||
// drawCatmullRom(context, topLeftApprox);
|
-FIXED_BINDING_DISTANCE,
|
||||||
// }
|
);
|
||||||
|
const bottomRightApprox = offsetQuadraticBezier(
|
||||||
|
pointFrom(element.width - radius, element.height),
|
||||||
|
pointFrom(element.width, element.height),
|
||||||
|
pointFrom(element.width, element.height - radius),
|
||||||
|
-FIXED_BINDING_DISTANCE,
|
||||||
|
);
|
||||||
|
const bottomLeftApprox = offsetQuadraticBezier(
|
||||||
|
pointFrom(0, element.height - radius),
|
||||||
|
pointFrom(0, element.height),
|
||||||
|
pointFrom(radius, element.height),
|
||||||
|
-FIXED_BINDING_DISTANCE,
|
||||||
|
);
|
||||||
|
|
||||||
|
context.moveTo(
|
||||||
|
topLeftApprox[topLeftApprox.length - 1][0],
|
||||||
|
topLeftApprox[topLeftApprox.length - 1][1],
|
||||||
|
);
|
||||||
|
context.lineTo(bottomLeftApprox[0][0], bottomLeftApprox[0][1]);
|
||||||
|
drawCatmullRomQuadraticApprox(context, bottomLeftApprox);
|
||||||
|
context.lineTo(bottomRightApprox[0][0], bottomRightApprox[0][1]);
|
||||||
|
drawCatmullRomQuadraticApprox(context, bottomRightApprox);
|
||||||
|
context.lineTo(topRightApprox[0][0], topRightApprox[0][1]);
|
||||||
|
drawCatmullRomQuadraticApprox(context, topRightApprox);
|
||||||
|
context.lineTo(topLeftApprox[0][0], topLeftApprox[0][1]);
|
||||||
|
drawCatmullRomQuadraticApprox(context, topLeftApprox);
|
||||||
|
}
|
||||||
|
|
||||||
context.closePath();
|
context.closePath();
|
||||||
context.fill();
|
context.fill();
|
||||||
|
@ -400,28 +393,28 @@ const strokeDiamondWithRotation = (
|
||||||
const horizontalRadius = element.roundness
|
const horizontalRadius = element.roundness
|
||||||
? getCornerRadius(Math.abs(rightY - topY), element)
|
? getCornerRadius(Math.abs(rightY - topY), element)
|
||||||
: (rightY - topY) * 0.01;
|
: (rightY - topY) * 0.01;
|
||||||
const topApprox = offsetBezier(
|
const topApprox = offsetCubicBezier(
|
||||||
pointFrom(topX - verticalRadius, topY + horizontalRadius),
|
pointFrom(topX - verticalRadius, topY + horizontalRadius),
|
||||||
pointFrom(topX, topY),
|
pointFrom(topX, topY),
|
||||||
pointFrom(topX, topY),
|
pointFrom(topX, topY),
|
||||||
pointFrom(topX + verticalRadius, topY + horizontalRadius),
|
pointFrom(topX + verticalRadius, topY + horizontalRadius),
|
||||||
padding,
|
padding,
|
||||||
);
|
);
|
||||||
const rightApprox = offsetBezier(
|
const rightApprox = offsetCubicBezier(
|
||||||
pointFrom(rightX - verticalRadius, rightY - horizontalRadius),
|
pointFrom(rightX - verticalRadius, rightY - horizontalRadius),
|
||||||
pointFrom(rightX, rightY),
|
pointFrom(rightX, rightY),
|
||||||
pointFrom(rightX, rightY),
|
pointFrom(rightX, rightY),
|
||||||
pointFrom(rightX - verticalRadius, rightY + horizontalRadius),
|
pointFrom(rightX - verticalRadius, rightY + horizontalRadius),
|
||||||
padding,
|
padding,
|
||||||
);
|
);
|
||||||
const bottomApprox = offsetBezier(
|
const bottomApprox = offsetCubicBezier(
|
||||||
pointFrom(bottomX + verticalRadius, bottomY - horizontalRadius),
|
pointFrom(bottomX + verticalRadius, bottomY - horizontalRadius),
|
||||||
pointFrom(bottomX, bottomY),
|
pointFrom(bottomX, bottomY),
|
||||||
pointFrom(bottomX, bottomY),
|
pointFrom(bottomX, bottomY),
|
||||||
pointFrom(bottomX - verticalRadius, bottomY - horizontalRadius),
|
pointFrom(bottomX - verticalRadius, bottomY - horizontalRadius),
|
||||||
padding,
|
padding,
|
||||||
);
|
);
|
||||||
const leftApprox = offsetBezier(
|
const leftApprox = offsetCubicBezier(
|
||||||
pointFrom(leftX + verticalRadius, leftY + horizontalRadius),
|
pointFrom(leftX + verticalRadius, leftY + horizontalRadius),
|
||||||
pointFrom(leftX, leftY),
|
pointFrom(leftX, leftY),
|
||||||
pointFrom(leftX, leftY),
|
pointFrom(leftX, leftY),
|
||||||
|
@ -434,13 +427,13 @@ const strokeDiamondWithRotation = (
|
||||||
topApprox[topApprox.length - 1][1],
|
topApprox[topApprox.length - 1][1],
|
||||||
);
|
);
|
||||||
context.lineTo(rightApprox[0][0], rightApprox[0][1]);
|
context.lineTo(rightApprox[0][0], rightApprox[0][1]);
|
||||||
drawCatmullRom(context, rightApprox);
|
drawCatmullRomCubicApprox(context, rightApprox);
|
||||||
context.lineTo(bottomApprox[0][0], bottomApprox[0][1]);
|
context.lineTo(bottomApprox[0][0], bottomApprox[0][1]);
|
||||||
drawCatmullRom(context, bottomApprox);
|
drawCatmullRomCubicApprox(context, bottomApprox);
|
||||||
context.lineTo(leftApprox[0][0], leftApprox[0][1]);
|
context.lineTo(leftApprox[0][0], leftApprox[0][1]);
|
||||||
drawCatmullRom(context, leftApprox);
|
drawCatmullRomCubicApprox(context, leftApprox);
|
||||||
context.lineTo(topApprox[0][0], topApprox[0][1]);
|
context.lineTo(topApprox[0][0], topApprox[0][1]);
|
||||||
drawCatmullRom(context, topApprox);
|
drawCatmullRomCubicApprox(context, topApprox);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Counter-clockwise for the cutout in the middle. We need to have an "inverse
|
// Counter-clockwise for the cutout in the middle. We need to have an "inverse
|
||||||
|
@ -455,28 +448,28 @@ const strokeDiamondWithRotation = (
|
||||||
const horizontalRadius = element.roundness
|
const horizontalRadius = element.roundness
|
||||||
? getCornerRadius(Math.abs(rightY - topY), element)
|
? getCornerRadius(Math.abs(rightY - topY), element)
|
||||||
: (rightY - topY) * 0.01;
|
: (rightY - topY) * 0.01;
|
||||||
const topApprox = offsetBezier(
|
const topApprox = offsetCubicBezier(
|
||||||
pointFrom(topX + verticalRadius, topY + horizontalRadius),
|
pointFrom(topX + verticalRadius, topY + horizontalRadius),
|
||||||
pointFrom(topX, topY),
|
pointFrom(topX, topY),
|
||||||
pointFrom(topX, topY),
|
pointFrom(topX, topY),
|
||||||
pointFrom(topX - verticalRadius, topY + horizontalRadius),
|
pointFrom(topX - verticalRadius, topY + horizontalRadius),
|
||||||
-FIXED_BINDING_DISTANCE,
|
-FIXED_BINDING_DISTANCE,
|
||||||
);
|
);
|
||||||
const rightApprox = offsetBezier(
|
const rightApprox = offsetCubicBezier(
|
||||||
pointFrom(rightX - verticalRadius, rightY + horizontalRadius),
|
pointFrom(rightX - verticalRadius, rightY + horizontalRadius),
|
||||||
pointFrom(rightX, rightY),
|
pointFrom(rightX, rightY),
|
||||||
pointFrom(rightX, rightY),
|
pointFrom(rightX, rightY),
|
||||||
pointFrom(rightX - verticalRadius, rightY - horizontalRadius),
|
pointFrom(rightX - verticalRadius, rightY - horizontalRadius),
|
||||||
-FIXED_BINDING_DISTANCE,
|
-FIXED_BINDING_DISTANCE,
|
||||||
);
|
);
|
||||||
const bottomApprox = offsetBezier(
|
const bottomApprox = offsetCubicBezier(
|
||||||
pointFrom(bottomX - verticalRadius, bottomY - horizontalRadius),
|
pointFrom(bottomX - verticalRadius, bottomY - horizontalRadius),
|
||||||
pointFrom(bottomX, bottomY),
|
pointFrom(bottomX, bottomY),
|
||||||
pointFrom(bottomX, bottomY),
|
pointFrom(bottomX, bottomY),
|
||||||
pointFrom(bottomX + verticalRadius, bottomY - horizontalRadius),
|
pointFrom(bottomX + verticalRadius, bottomY - horizontalRadius),
|
||||||
-FIXED_BINDING_DISTANCE,
|
-FIXED_BINDING_DISTANCE,
|
||||||
);
|
);
|
||||||
const leftApprox = offsetBezier(
|
const leftApprox = offsetCubicBezier(
|
||||||
pointFrom(leftX + verticalRadius, leftY - horizontalRadius),
|
pointFrom(leftX + verticalRadius, leftY - horizontalRadius),
|
||||||
pointFrom(leftX, leftY),
|
pointFrom(leftX, leftY),
|
||||||
pointFrom(leftX, leftY),
|
pointFrom(leftX, leftY),
|
||||||
|
@ -489,13 +482,13 @@ const strokeDiamondWithRotation = (
|
||||||
topApprox[topApprox.length - 1][1],
|
topApprox[topApprox.length - 1][1],
|
||||||
);
|
);
|
||||||
context.lineTo(leftApprox[0][0], leftApprox[0][1]);
|
context.lineTo(leftApprox[0][0], leftApprox[0][1]);
|
||||||
drawCatmullRom(context, leftApprox);
|
drawCatmullRomCubicApprox(context, leftApprox);
|
||||||
context.lineTo(bottomApprox[0][0], bottomApprox[0][1]);
|
context.lineTo(bottomApprox[0][0], bottomApprox[0][1]);
|
||||||
drawCatmullRom(context, bottomApprox);
|
drawCatmullRomCubicApprox(context, bottomApprox);
|
||||||
context.lineTo(rightApprox[0][0], rightApprox[0][1]);
|
context.lineTo(rightApprox[0][0], rightApprox[0][1]);
|
||||||
drawCatmullRom(context, rightApprox);
|
drawCatmullRomCubicApprox(context, rightApprox);
|
||||||
context.lineTo(topApprox[0][0], topApprox[0][1]);
|
context.lineTo(topApprox[0][0], topApprox[0][1]);
|
||||||
drawCatmullRom(context, topApprox);
|
drawCatmullRomCubicApprox(context, topApprox);
|
||||||
}
|
}
|
||||||
context.closePath();
|
context.closePath();
|
||||||
context.fill();
|
context.fill();
|
||||||
|
@ -1512,7 +1505,33 @@ export const renderInteractiveScene = <
|
||||||
return ret as T extends true ? void : ReturnType<U>;
|
return ret as T extends true ? void : ReturnType<U>;
|
||||||
};
|
};
|
||||||
|
|
||||||
function drawCatmullRom(
|
function drawCatmullRomQuadraticApprox(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
points: GlobalPoint[],
|
||||||
|
segments = 20,
|
||||||
|
) {
|
||||||
|
ctx.lineTo(points[0][0], points[0][1]);
|
||||||
|
|
||||||
|
for (let i = 0; i < points.length - 1; i++) {
|
||||||
|
const p0 = points[i - 1 < 0 ? 0 : i - 1];
|
||||||
|
const p1 = points[i];
|
||||||
|
const p2 = points[i + 1 >= points.length ? points.length - 1 : i + 1];
|
||||||
|
|
||||||
|
for (let t = 0; t <= 1; t += 1 / segments) {
|
||||||
|
const t2 = t * t;
|
||||||
|
|
||||||
|
const x =
|
||||||
|
(1 - t) * (1 - t) * p0[0] + 2 * (1 - t) * t * p1[0] + t2 * p2[0];
|
||||||
|
|
||||||
|
const y =
|
||||||
|
(1 - t) * (1 - t) * p0[1] + 2 * (1 - t) * t * p1[1] + t2 * p2[1];
|
||||||
|
|
||||||
|
ctx.lineTo(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawCatmullRomCubicApprox(
|
||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
points: GlobalPoint[],
|
points: GlobalPoint[],
|
||||||
segments = 20,
|
segments = 20,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue