diff --git a/packages/element/src/utils.ts b/packages/element/src/utils.ts index b270c5105..110574ca9 100644 --- a/packages/element/src/utils.ts +++ b/packages/element/src/utils.ts @@ -1,5 +1,7 @@ import { curve, + curveCatmullRomCubicApproxPoints, + curveOffsetPoints, lineSegment, pointFrom, pointFromArray, @@ -299,10 +301,10 @@ export function deconstructDiamondElement( if (element.roundness?.type == null) { const [top, right, bottom, left]: GlobalPoint[] = [ - pointFrom(element.x + topX, element.y + topY - offset), - pointFrom(element.x + rightX + offset, element.y + rightY), - pointFrom(element.x + bottomX, element.y + bottomY + offset), - pointFrom(element.x + leftX - offset, element.y + leftY), + pointFrom(element.x + topX, element.y + topY), + pointFrom(element.x + rightX, element.y + rightY), + pointFrom(element.x + bottomX, element.y + bottomY), + pointFrom(element.x + leftX, element.y + leftY), ]; // Create the line segment parts of the diamond @@ -336,26 +338,26 @@ export function deconstructDiamondElement( pointFrom(element.x + leftX, element.y + leftY), ]; - const offsets = [ - vectorScale(vectorNormalize(vectorFromPoint(right, center)), offset), // RIGHT - vectorScale(vectorNormalize(vectorFromPoint(bottom, center)), offset), // BOTTOM - vectorScale(vectorNormalize(vectorFromPoint(left, center)), offset), // LEFT - vectorScale(vectorNormalize(vectorFromPoint(top, center)), offset), // TOP + const cornerPoints = [ + vectorScale(vectorNormalize(vectorFromPoint(right, center)), 0), // RIGHT + vectorScale(vectorNormalize(vectorFromPoint(bottom, center)), 0), // BOTTOM + vectorScale(vectorNormalize(vectorFromPoint(left, center)), 0), // LEFT + vectorScale(vectorNormalize(vectorFromPoint(top, center)), 0), // TOP ]; - const corners = [ + const baseCorners = [ curve( pointFromVector( - offsets[0], + cornerPoints[0], pointFrom( right[0] - verticalRadius, right[1] - horizontalRadius, ), ), - pointFromVector(offsets[0], right), - pointFromVector(offsets[0], right), + pointFromVector(cornerPoints[0], right), + pointFromVector(cornerPoints[0], right), pointFromVector( - offsets[0], + cornerPoints[0], pointFrom( right[0] - verticalRadius, right[1] + horizontalRadius, @@ -364,16 +366,16 @@ export function deconstructDiamondElement( ), // RIGHT curve( pointFromVector( - offsets[1], + cornerPoints[1], pointFrom( bottom[0] + verticalRadius, bottom[1] - horizontalRadius, ), ), - pointFromVector(offsets[1], bottom), - pointFromVector(offsets[1], bottom), + pointFromVector(cornerPoints[1], bottom), + pointFromVector(cornerPoints[1], bottom), pointFromVector( - offsets[1], + cornerPoints[1], pointFrom( bottom[0] - verticalRadius, bottom[1] - horizontalRadius, @@ -382,16 +384,16 @@ export function deconstructDiamondElement( ), // BOTTOM curve( pointFromVector( - offsets[2], + cornerPoints[2], pointFrom( left[0] + verticalRadius, left[1] + horizontalRadius, ), ), - pointFromVector(offsets[2], left), - pointFromVector(offsets[2], left), + pointFromVector(cornerPoints[2], left), + pointFromVector(cornerPoints[2], left), pointFromVector( - offsets[2], + cornerPoints[2], pointFrom( left[0] + verticalRadius, left[1] - horizontalRadius, @@ -400,16 +402,16 @@ export function deconstructDiamondElement( ), // LEFT curve( pointFromVector( - offsets[3], + cornerPoints[3], pointFrom( top[0] - verticalRadius, top[1] + horizontalRadius, ), ), - pointFromVector(offsets[3], top), - pointFromVector(offsets[3], top), + pointFromVector(cornerPoints[3], top), + pointFromVector(cornerPoints[3], top), pointFromVector( - offsets[3], + cornerPoints[3], pointFrom( top[0] + verticalRadius, top[1] + horizontalRadius, @@ -418,12 +420,39 @@ export function deconstructDiamondElement( ), // TOP ]; + const corners = + offset > 0 + ? baseCorners.map( + (corner) => + curveCatmullRomCubicApproxPoints( + curveOffsetPoints(corner, offset), + )!, + ) + : [ + [baseCorners[0]], + [baseCorners[1]], + [baseCorners[2]], + [baseCorners[3]], + ]; + const sides = [ - lineSegment(corners[0][3], corners[1][0]), - lineSegment(corners[1][3], corners[2][0]), - lineSegment(corners[2][3], corners[3][0]), - lineSegment(corners[3][3], corners[0][0]), + lineSegment( + corners[0][corners[0].length - 1][3], + corners[1][0][0], + ), + lineSegment( + corners[1][corners[1].length - 1][3], + corners[2][0][0], + ), + lineSegment( + corners[2][corners[2].length - 1][3], + corners[3][0][0], + ), + lineSegment( + corners[3][corners[3].length - 1][3], + corners[0][0][0], + ), ]; - return [sides, corners]; + return [sides, corners.flat()]; } diff --git a/packages/excalidraw/renderer/helpers.ts b/packages/excalidraw/renderer/helpers.ts index a06425ea6..df3a0e680 100644 --- a/packages/excalidraw/renderer/helpers.ts +++ b/packages/excalidraw/renderer/helpers.ts @@ -345,13 +345,13 @@ export const drawHighlightForDiamondWithRotation = ( topApprox[topApprox.length - 1][0], topApprox[topApprox.length - 1][1], ); - context.lineTo(rightApprox[0][0], rightApprox[0][1]); + context.lineTo(rightApprox[1][0], rightApprox[1][1]); drawCatmullRomCubicApprox(context, rightApprox); - context.lineTo(bottomApprox[0][0], bottomApprox[0][1]); + context.lineTo(bottomApprox[1][0], bottomApprox[1][1]); drawCatmullRomCubicApprox(context, bottomApprox); - context.lineTo(leftApprox[0][0], leftApprox[0][1]); + context.lineTo(leftApprox[1][0], leftApprox[1][1]); drawCatmullRomCubicApprox(context, leftApprox); - context.lineTo(topApprox[0][0], topApprox[0][1]); + context.lineTo(topApprox[1][0], topApprox[1][1]); drawCatmullRomCubicApprox(context, topApprox); } @@ -408,13 +408,13 @@ export const drawHighlightForDiamondWithRotation = ( topApprox[topApprox.length - 1][0], topApprox[topApprox.length - 1][1], ); - context.lineTo(leftApprox[0][0], leftApprox[0][1]); + context.lineTo(leftApprox[1][0], leftApprox[1][1]); drawCatmullRomCubicApprox(context, leftApprox); - context.lineTo(bottomApprox[0][0], bottomApprox[0][1]); + context.lineTo(bottomApprox[1][0], bottomApprox[1][1]); drawCatmullRomCubicApprox(context, bottomApprox); - context.lineTo(rightApprox[0][0], rightApprox[0][1]); + context.lineTo(rightApprox[1][0], rightApprox[1][1]); drawCatmullRomCubicApprox(context, rightApprox); - context.lineTo(topApprox[0][0], topApprox[0][1]); + context.lineTo(topApprox[1][0], topApprox[1][1]); drawCatmullRomCubicApprox(context, topApprox); } context.closePath(); diff --git a/packages/math/src/curve.ts b/packages/math/src/curve.ts index d7f6a7341..e0ae7770d 100644 --- a/packages/math/src/curve.ts +++ b/packages/math/src/curve.ts @@ -329,15 +329,14 @@ export function curveCatmullRomQuadraticApproxPoints( return pointSets; } -export function curveCatmullRomCubicApproxPoints( - points: GlobalPoint[], - tension = 0.5, -) { +export function curveCatmullRomCubicApproxPoints< + Point extends GlobalPoint | LocalPoint, +>(points: Point[], tension = 0.5) { if (points.length < 2) { return; } - const pointSets: [GlobalPoint, GlobalPoint, GlobalPoint][] = []; + const pointSets: Curve[] = []; for (let i = 0; i < points.length - 1; i++) { const p0 = points[i - 1 < 0 ? 0 : i - 1]; const p1 = points[i]; @@ -350,11 +349,14 @@ export function curveCatmullRomCubicApproxPoints( const cp2x = p2[0] - tangent2[0] / 3; const cp2y = p2[1] - tangent2[1] / 3; - pointSets.push([ - pointFrom(cp1x, cp1y), - pointFrom(cp2x, cp2y), - pointFrom(p2[0], p2[1]), - ]); + pointSets.push( + curve( + pointFrom(p1[0], p1[1]), + pointFrom(cp1x, cp1y), + pointFrom(cp2x, cp2y), + pointFrom(p2[0], p2[1]), + ), + ); } return pointSets; @@ -362,7 +364,7 @@ export function curveCatmullRomCubicApproxPoints( export function curveOffsetPoints( [p0, p1, p2, p3]: Curve, - offsetDist: number, + offset: number, steps = 50, ) { const offsetPoints = []; @@ -374,7 +376,7 @@ export function curveOffsetPoints( const tangent = vectorNormalize(curveTangent(c, t)); const normal = vectorNormal(tangent); - offsetPoints.push(pointFromVector(vectorScale(normal, offsetDist), point)); + offsetPoints.push(pointFromVector(vectorScale(normal, offset), point)); } return offsetPoints;