diff --git a/svelte-app/src/lib/export.ts b/svelte-app/src/lib/export.ts index f778ef8..2229702 100644 --- a/svelte-app/src/lib/export.ts +++ b/svelte-app/src/lib/export.ts @@ -17,55 +17,47 @@ function parseConveyanceLabel(label: string): { lines: string[]; stripped: strin return { lines: [core], stripped: [core] }; } -/** Emit conveyance label text element inside the shape */ -function emitConveyanceLabel(lines: string[], sym: PlacedSymbol, outerTransform: string) { +/** Emit conveyance label text — absolute coordinates, no transforms (Ignition compatible) */ +function emitConveyanceLabel(lines: string[], sym: PlacedSymbol, _outerTransform: string) { if (!sym.label) return; - const { lines: textLines, stripped } = parseConveyanceLabel(sym.label); - const tAttr = outerTransform ? ` transform="${outerTransform}"` : ''; + const { lines: textLines } = parseConveyanceLabel(sym.label); + + // Compute label center position based on shape type + let labelCx: number, labelCy: number, availH: number; - // Curved symbols: place along arc midpoint if (isCurvedType(sym.symbolId)) { const angle = sym.curveAngle || 90; const { arcCx, arcCy, outerR, innerR, bandW } = getCurveGeometry(sym.symbolId, sym.x, sym.y, sym.w, sym.h); const midR = (outerR + innerR) / 2; const midAngleRad = ((angle / 2) * Math.PI) / 180; - const textX = arcCx + midR * Math.cos(midAngleRad); - const textY = arcCy - midR * Math.sin(midAngleRad); - const rotDeg = -angle / 2 + 90; - const fontSize = Math.min(14, (bandW - 4) / textLines.length); - if (fontSize < 4) return; - const lineH = fontSize; - const curveTransform = `translate(${textX},${textY}) rotate(${rotDeg})${outerTransform ? ' ' + outerTransform : ''}`; - for (let i = 0; i < textLines.length; i++) { - const dy = -(textLines.length - 1) * lineH / 2 + i * lineH; - lines.push(` ${textLines[i]}`); - } - return; - } - - // Spur: center in trapezoid - let labelCx: number, labelCy: number, availW: number, availH: number; - if (isSpurType(sym.symbolId)) { + labelCx = arcCx + midR * Math.cos(midAngleRad); + labelCy = arcCy - midR * Math.sin(midAngleRad); + availH = bandW - 4; + } else if (isSpurType(sym.symbolId)) { const w2 = sym.w2 ?? sym.w; - const midW = (w2 + sym.w) / 2; - labelCx = sym.x + midW / 2; + labelCx = sym.x + (w2 + sym.w) / 4; labelCy = sym.y + sym.h / 2; - availW = midW - 4; availH = sym.h - 4; + } else if (isInductionType(sym.symbolId)) { + const stripTopY = sym.y + sym.h * INDUCTION_CONFIG.stripTopFrac; + const stripBottomY = sym.y + sym.h * INDUCTION_CONFIG.stripBottomFrac; + labelCx = sym.x + (INDUCTION_CONFIG.headWidth + sym.w) / 2; + labelCy = (stripTopY + stripBottomY) / 2; + availH = stripBottomY - stripTopY - 4; } else { labelCx = sym.x + sym.w / 2; labelCy = sym.y + sym.h / 2; - availW = sym.w - 4; availH = sym.h - 4; } - const useLines = textLines; - const fontSize = Math.min(14, availH / useLines.length); + const fontSize = Math.min(14, availH / textLines.length); if (fontSize < 4) return; const lineH = fontSize; - for (let i = 0; i < useLines.length; i++) { - const dy = -(useLines.length - 1) * lineH / 2 + i * lineH; - lines.push(` ${useLines[i]}`); + // Emit each line at absolute position — y is baseline, offset by 0.35*fontSize to center visually + for (let i = 0; i < textLines.length; i++) { + const dy = -(textLines.length - 1) * lineH / 2 + i * lineH; + const y = labelCy + dy + fontSize * 0.35; + lines.push(` ${textLines[i]}`); } }