From c3da2da20d050839a94480e51f58fdeefac62d4e Mon Sep 17 00:00:00 2001 From: igurielidze Date: Mon, 30 Mar 2026 15:18:54 +0400 Subject: [PATCH] Fix EPC symbol jump on mouseup: preserve rotation center when updating bounds recalcEpcBounds now properly normalizes the bounding box to start at (0,0) in local space, adjusting sym.x/y to compensate so the world position and rotation center stay constant. Handles rotated symbols by rotating the center offset into world space. Co-Authored-By: Claude Opus 4.6 (1M context) --- svelte-app/src/lib/canvas/interactions.ts | 34 +++++++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/svelte-app/src/lib/canvas/interactions.ts b/svelte-app/src/lib/canvas/interactions.ts index 70fe533..541214a 100644 --- a/svelte-app/src/lib/canvas/interactions.ts +++ b/svelte-app/src/lib/canvas/interactions.ts @@ -370,9 +370,37 @@ function recalcEpcBounds(sym: typeof layout.symbols[0]) { // Add small padding minX -= 1; minY -= 1; maxX += 1; maxY += 1; - // Set w/h to cover full extent from origin (allow negative local coords) - sym.w = Math.max(maxX, 1); - sym.h = Math.max(maxY, 1); + const newW = Math.max(maxX - minX, 1); + const newH = Math.max(maxY - minY, 1); + + // Compute old and new rotation centers (local space) + const oldCx = sym.w / 2; + const oldCy = sym.h / 2; + const newCx = minX + newW / 2; + const newCy = minY + newH / 2; + + // Shift origin so the rotation center stays at the same world position. + // For rotated symbols, the center offset must be rotated into world space. + const dCx = newCx - oldCx; + const dCy = newCy - oldCy; + if (sym.rotation) { + const rad = (sym.rotation * Math.PI) / 180; + const cos = Math.cos(rad), sin = Math.sin(rad); + sym.x += cos * dCx - sin * dCy; + sym.y += sin * dCx + cos * dCy; + } else { + sym.x += dCx; + sym.y += dCy; + } + + // Adjust waypoints so their local coords are relative to the new origin + for (const wp of wps) { + wp.x -= minX; + wp.y -= minY; + } + + sym.w = newW; + sym.h = newH; } function snapWidth(w: number, ctrlKey: boolean, minW: number = CONVEYOR_MIN_W): number {