diff --git a/frontend/src/services/exportService.ts b/frontend/src/services/exportService.ts index ffce33b..7480b4c 100644 --- a/frontend/src/services/exportService.ts +++ b/frontend/src/services/exportService.ts @@ -75,15 +75,14 @@ function hexToRgb(hex: string): { r: number; g: number; b: number } { } function rgbToAci(r: number, g: number, b: number): number { - // Simplified ACI color mapping - if (r > 200 && g > 200 && b > 200) return 7; // white - if (r < 50 && g < 50 && b < 50) return 7; // black → white in DXF - if (r > 200 && g < 100 && b < 100) return 1; // red - if (r < 100 && g > 200 && b < 100) return 3; // green - if (r < 100 && g < 100 && b > 200) return 5; // blue - if (r > 200 && g > 200 && b < 100) return 2; // yellow - if (r > 200 && g < 100 && b > 200) return 6; // magenta - if (r < 100 && g > 200 && b > 200) return 4; // cyan + if (r > 200 && g > 200 && b > 200) return 7; + if (r < 50 && g < 50 && b < 50) return 7; + if (r > 200 && g < 100 && b < 100) return 1; + if (r < 100 && g > 200 && b < 100) return 3; + if (r < 100 && g < 100 && b > 200) return 5; + if (r > 200 && g > 200 && b < 100) return 2; + if (r > 200 && g < 100 && b > 200) return 6; + if (r < 100 && g > 200 && b > 200) return 4; return 7; } @@ -167,7 +166,6 @@ export function exportJSONString(yjsDoc: YjsDocument): string { export function exportSVG(yjsDoc: YjsDocument, filename = 'cad-export.svg', options: ExportOptions = {}): void { const data = collectExportData(yjsDoc, options); - // Calculate bounding box let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity; for (const el of data.elements) { minX = Math.min(minX, el.x); @@ -189,7 +187,6 @@ export function exportSVG(yjsDoc: YjsDocument, filename = 'cad-export.svg', opti svgParts.push(``); svgParts.push(``); - // Layer styles svgParts.push(''); - // Elements (Y-axis flipped for SVG coordinate system) for (const el of data.elements) { const layer = getLayerById(data.layers, el.layerId); - const layerClass = layer ? `class="layer-${layer.id}"` : ''; const stroke = el.properties.stroke || layer?.color || '#000000'; const fill = el.properties.fill || 'none'; const strokeWidth = el.properties.strokeWidth || 1; const transform = el.properties.rotation ? ` transform="rotate(${el.properties.rotation} ${el.x + el.width / 2} ${el.y + el.height / 2})"` : ''; - // SVG Y-axis is inverted compared to CAD const svgY = (vbY + vbH) - el.y; switch (el.type) { @@ -251,7 +245,6 @@ export function exportSVG(yjsDoc: YjsDocument, filename = 'cad-export.svg', opti break; } case 'arc': { - // Approximate arc with path (simplified: use bounding box) const rx = el.width / 2; const ry = el.height / 2; const cx = el.x + rx; @@ -260,7 +253,6 @@ export function exportSVG(yjsDoc: YjsDocument, filename = 'cad-export.svg', opti break; } default: - // Unknown type: skip break; } } @@ -276,7 +268,6 @@ export function exportDXF(yjsDoc: YjsDocument, filename = 'cad-export.dxf', opti const data = collectExportData(yjsDoc, options); const lines: string[] = []; - // HEADER section lines.push('0'); lines.push('SECTION'); lines.push('2'); lines.push('HEADER'); lines.push('9'); lines.push('$ACADVER'); @@ -287,7 +278,6 @@ export function exportDXF(yjsDoc: YjsDocument, filename = 'cad-export.dxf', opti lines.push('30'); lines.push('0.0'); lines.push('0'); lines.push('ENDSEC'); - // TABLES section — LAYER table lines.push('0'); lines.push('SECTION'); lines.push('2'); lines.push('TABLES'); lines.push('0'); lines.push('TABLE'); @@ -308,7 +298,6 @@ export function exportDXF(yjsDoc: YjsDocument, filename = 'cad-export.dxf', opti lines.push('0'); lines.push('ENDTAB'); lines.push('0'); lines.push('ENDSEC'); - // ENTITIES section lines.push('0'); lines.push('SECTION'); lines.push('2'); lines.push('ENTITIES'); @@ -350,13 +339,12 @@ export function exportDXF(yjsDoc: YjsDocument, filename = 'cad-export.dxf', opti break; } case 'rect': { - // Export as LWPOLYLINE (4 corners) const x = el.x, y = el.y, w = el.width, h = el.height; lines.push('0'); lines.push('LWPOLYLINE'); lines.push('8'); lines.push(layerName); lines.push('62'); lines.push(String(aci)); lines.push('90'); lines.push('4'); - lines.push('70'); lines.push('1'); // closed + lines.push('70'); lines.push('1'); lines.push('10'); lines.push(String(x)); lines.push('20'); lines.push(String(y)); lines.push('10'); lines.push(String(x + w)); lines.push('20'); lines.push(String(y)); lines.push('10'); lines.push(String(x + w)); lines.push('20'); lines.push(String(y + h)); @@ -383,7 +371,7 @@ export function exportDXF(yjsDoc: YjsDocument, filename = 'cad-export.dxf', opti lines.push('8'); lines.push(layerName); lines.push('62'); lines.push(String(aci)); lines.push('90'); lines.push(String(pts.length)); - lines.push('70'); lines.push('0'); // open + lines.push('70'); lines.push('0'); for (const p of pts) { lines.push('10'); lines.push(String(p.x)); lines.push('20'); lines.push(String(p.y)); @@ -398,7 +386,7 @@ export function exportDXF(yjsDoc: YjsDocument, filename = 'cad-export.dxf', opti lines.push('8'); lines.push(layerName); lines.push('62'); lines.push(String(aci)); lines.push('90'); lines.push(String(pts.length)); - lines.push('70'); lines.push('1'); // closed + lines.push('70'); lines.push('1'); for (const p of pts) { lines.push('10'); lines.push(String(p.x)); lines.push('20'); lines.push(String(p.y)); @@ -427,8 +415,6 @@ export function exportDXF(yjsDoc: YjsDocument, filename = 'cad-export.dxf', opti } lines.push('0'); lines.push('ENDSEC'); - - // EOF lines.push('0'); lines.push('EOF'); const dxf = lines.join('\n'); @@ -444,7 +430,6 @@ export async function exportPDF( ): Promise { const data = collectExportData(yjsDoc, options); - // Dynamic import to avoid bundling jsPDF if not used const { jsPDF } = await import('jspdf'); const pageSize = options.pageSize || 'a4'; @@ -461,7 +446,6 @@ export async function exportPDF( const drawableW = pageWidth - margin * 2; const drawableH = pageHeight - margin * 2; - // Calculate bounding box and scale to fit let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity; for (const el of data.elements) { minX = Math.min(minX, el.x); @@ -479,11 +463,9 @@ export async function exportPDF( const offsetX = margin + (drawableW - contentW * scale) / 2; const offsetY = margin + (drawableH - contentH * scale) / 2; - // Transform CAD coords to PDF coords (Y-axis flip) const tx = (x: number) => offsetX + (x - minX) * scale; const ty = (y: number) => pageHeight - offsetY - (y - minY) * scale; - // Draw elements for (const el of data.elements) { const layer = getLayerById(data.layers, el.layerId); const strokeColor = el.properties.stroke || layer?.color || '#000000'; @@ -515,7 +497,7 @@ export async function exportPDF( } case 'rect': { const x = tx(el.x); - const y = ty(el.y + el.height); // flip + const y = ty(el.y + el.height); pdf.rect(x, y, el.width * scale, el.height * scale, fillColor && fillColor !== 'transparent' ? 'FD' : 'S'); break; } @@ -557,7 +539,6 @@ export async function exportPDF( } } - // Plan header pdf.setFontSize(8); pdf.setTextColor(128, 128, 128); pdf.text(