From 84c3b4425397e1bcae891aa32e087f78e8fee6f5 Mon Sep 17 00:00:00 2001 From: Burak Eyler Date: Sun, 13 Sep 2026 14:39:32 +0300 Subject: [PATCH] fix: normalize exported polygon points against the rendered canvas showCytoArray divided by a hardcoded 260px half-extent, but the SVG has no viewBox and fills its container, so at most viewport widths the exported points left the -1..1 range and the visible centre did not export 0. Use the same rect-derived normalizeToCanvas the hover readout uses, so the export and the readout agree. Fixes #212 Co-Authored-By: Claude Opus 5 Signed-off-by: Burak Eyler --- site/src/components/ShapeBuilder/index.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/site/src/components/ShapeBuilder/index.js b/site/src/components/ShapeBuilder/index.js index 6f05baf..f95fc97 100644 --- a/site/src/components/ShapeBuilder/index.js +++ b/site/src/components/ShapeBuilder/index.js @@ -19,11 +19,10 @@ const READOUT_PRECISION = 3; /* * Maps a point in canvas pixels onto -1..1 relative to the canvas centre. - * Note this is measured off the live element, whereas `showCytoArray` still - * normalizes against a hardcoded 260px half-extent; the two agree only while - * the canvas is 520px square, which it is not at most viewport widths. That - * hardcoded divisor predates this feature and is left for a separate change so - * the polygon output contract is not altered here. + * The SVG has no viewBox, so its user space is CSS pixels at whatever size the + * viewport gives it; the half-extents must come from the rendered rect, never + * a fixed canvas size. Both the export and the hover readout go through here + * so the two always agree. */ const normalizeToCanvas = (x, y, rect) => [ (x - rect.width / 2) / (rect.width / 2), @@ -94,8 +93,11 @@ const ShapeBuilder = () => { const points = getPlottedPoints(poly); if (!points) throw new Error("Invalid or empty polygon points"); + const rect = boardRef.current?.getBoundingClientRect(); + if (!rect?.width || !rect?.height) throw new Error("Canvas has no rendered size"); + const normalized = points - .map(([x, y]) => [(x - 260) / 260, (y - 260) / 260]) + .map(([x, y]) => normalizeToCanvas(x, y, rect)) .flat() .join(" "); setResult(normalized);