111 lines
3.8 KiB
JavaScript
111 lines
3.8 KiB
JavaScript
import { generateCuttingList } from './cuttingEngine.js';
|
|
import { collectHoleSpecsForPiece } from './holeSpecifications.js';
|
|
import { GROOVE, getBackGroovePlanOrientation } from '../../shared/manufacturing.js';
|
|
|
|
function toSafeNumber(value, fallback = 0) {
|
|
const n = Number(value);
|
|
return Number.isFinite(n) ? n : fallback;
|
|
}
|
|
|
|
function toLabel(value) {
|
|
return String(value || '')
|
|
.replace(/[^a-zA-Z0-9_\-]+/g, '_')
|
|
.replace(/_+/g, '_')
|
|
.replace(/^_+|_+$/g, '')
|
|
.toUpperCase();
|
|
}
|
|
|
|
function emitPanelOutline(lines, widthMm, heightMm, safeZ, cutZ, feed) {
|
|
lines.push(`G0 Z${safeZ.toFixed(3)}`);
|
|
lines.push('G0 X0.000 Y0.000');
|
|
lines.push(`G1 Z${cutZ.toFixed(3)} F${Math.round(feed)}`);
|
|
lines.push(`G1 X${widthMm.toFixed(3)} Y0.000`);
|
|
lines.push(`G1 X${widthMm.toFixed(3)} Y${heightMm.toFixed(3)}`);
|
|
lines.push(`G1 X0.000 Y${heightMm.toFixed(3)}`);
|
|
lines.push('G1 X0.000 Y0.000');
|
|
lines.push(`G0 Z${safeZ.toFixed(3)}`);
|
|
}
|
|
|
|
function emitHole(lines, { xMm, yMm, diameterMm = 5, depthMm = 10, type = 'generic', face = 'face', end = null }) {
|
|
let tail = `TYPE=${String(type)} FACE=${face}`;
|
|
if (end) tail += ` END=${end}`;
|
|
lines.push(
|
|
`; HOLE X=${Number(xMm).toFixed(3)} Y=${Number(yMm).toFixed(3)} D=${Number(diameterMm).toFixed(3)} Z=${Number(depthMm).toFixed(3)} ${tail}`
|
|
);
|
|
}
|
|
|
|
function emitPieceHoleComments(lines, piece, widthMm, heightMm, partIndex = 0) {
|
|
const { specs, thicknessMm: _tm } = collectHoleSpecsForPiece(piece, widthMm, heightMm, partIndex);
|
|
for (const spec of specs) {
|
|
emitHole(lines, spec);
|
|
}
|
|
|
|
const m = piece?.machining || {};
|
|
const orient = piece?.elementType ? getBackGroovePlanOrientation(piece.elementType) : null;
|
|
if (m.groove && orient) {
|
|
const gw = Number(m.groove.width ?? GROOVE.back.width);
|
|
const gd = Number(m.groove.depth ?? GROOVE.back.depth);
|
|
const ax = Number(m.groove.axisFromPanelEdge ?? m.groove.axisFromBackEdge ?? GROOVE.back.axisFromPanelEdge);
|
|
lines.push(`; GROOVE BACK W=${gw.toFixed(3)} D=${gd.toFixed(3)} AXIS=${ax.toFixed(3)} ORIENT=${orient}`);
|
|
}
|
|
}
|
|
|
|
export function generateCncProgram(config, modules = [], colors = {}) {
|
|
const cuttingList = generateCuttingList(config, colors, modules);
|
|
|
|
const safeZ = 10;
|
|
const cutDepth = 3;
|
|
const feedCut = 1800;
|
|
|
|
const lines = [
|
|
'%',
|
|
'; APEX CNC ISO (G-code) - v1',
|
|
`; Generated: ${new Date().toISOString()}`,
|
|
`; Config: ${config.widthMm}x${config.heightMm}x${config.depthMm} mm`,
|
|
'G21 ; metric units',
|
|
'G90 ; absolute coordinates',
|
|
'G17 ; XY plane',
|
|
`G0 Z${safeZ.toFixed(3)}`
|
|
];
|
|
|
|
let programPartCount = 0;
|
|
|
|
for (const piece of cuttingList.pieces || []) {
|
|
const widthMm = toSafeNumber(piece.rawCutWidthMm, piece.widthMm);
|
|
const heightMm = toSafeNumber(piece.rawCutHeightMm, piece.heightMm);
|
|
const qty = Math.max(1, Math.round(toSafeNumber(piece.quantity, 1)));
|
|
const thickness = toSafeNumber(piece.thicknessMm, 19);
|
|
const pieceName = toLabel(piece.description || piece.elementType || 'PIECE');
|
|
const targetDepth = -Math.min(cutDepth, Math.max(1, thickness * 0.25));
|
|
|
|
for (let i = 0; i < qty; i++) {
|
|
programPartCount += 1;
|
|
lines.push('');
|
|
lines.push(`; --- PART ${programPartCount}: ${pieceName} #${i + 1} ---`);
|
|
lines.push(`; SIZE_RAW: X=${widthMm.toFixed(3)} Y=${heightMm.toFixed(3)} T=${thickness.toFixed(3)}`);
|
|
emitPieceHoleComments(lines, piece, widthMm, heightMm, i);
|
|
emitPanelOutline(lines, widthMm, heightMm, safeZ, targetDepth, feedCut);
|
|
}
|
|
}
|
|
|
|
lines.push('');
|
|
lines.push(`G0 Z${safeZ.toFixed(3)}`);
|
|
lines.push('G0 X0.000 Y0.000');
|
|
lines.push('M30');
|
|
lines.push('%');
|
|
|
|
return {
|
|
fileName: 'apex-program.nc',
|
|
mimeType: 'text/plain; charset=utf-8',
|
|
content: lines.join('\n'),
|
|
metadata: {
|
|
generatedAt: new Date().toISOString(),
|
|
parts: programPartCount
|
|
}
|
|
};
|
|
}
|
|
|
|
export default {
|
|
generateCncProgram
|
|
};
|