Files
apex/server/services/holeSpecifications.js
T
lejayandCursor 6c0d7e47b8 v2.0
Co-authored-by: Cursor <[email protected]>
2026-05-28 07:20:38 +02:00

135 lines
4.3 KiB
JavaScript

/**
* Perçages par pièce pour exports CNC (.nc) et MPR (HOMAC/Woodwop XML-like).
* Même jeu de coordonnées que la vue liste / G-code commentaires : origine bas-gauche, X/Y en mm.
*/
import {
buildTopBottomPlanHoleSpecsMm,
buildVerticalPanelIxconnectFaceHoleSpecsMm,
buildShelfMobileHoleSpecsMm,
buildFinishHabillageHoleSpecsMm,
buildDoorHingeCupHoleSpecsMm,
buildDrawerReinforcementHoleSpecsMm,
buildDrawerRenfortPanelIxconnectSpecsMm
} from '../../shared/cncPanelHoles.js';
export function collectHoleSpecsForPiece(piece, widthMm, heightMm, partIndex = 0) {
const specs = [];
function pushHole(params) {
specs.push(params);
}
const m = piece?.machining || {};
const thicknessMm = Math.max(1, Number(piece?.thicknessMm) || 19);
const clampX = (v) => Math.max(0, Math.min(widthMm, Number(v) || 0));
const clampY = (v) => Math.max(0, Math.min(heightMm, Number(v) || 0));
if (m.system32?.positions?.length) {
const frontX = clampX(37);
const backX = clampX(widthMm - 37);
const d = Number(m.system32.holeDiameter || 5);
const z = Number(m.system32.holeDepth || piece.thicknessMm || 12);
const throughHole = Boolean(m.system32.throughHole);
for (const pos of m.system32.positions) {
const y = clampY(pos);
pushHole({
xMm: frontX,
yMm: y,
diameterMm: d,
depthMm: z,
type: 'system32',
face: 'face',
toolMode: throughHole ? 'through' : 'blind'
});
pushHole({
xMm: backX,
yMm: y,
diameterMm: d,
depthMm: z,
type: 'system32',
face: 'face',
toolMode: throughHole ? 'through' : 'blind'
});
}
}
if (['dessus', 'fond'].includes(piece.elementType || '')) {
for (const spec of buildTopBottomPlanHoleSpecsMm(piece, widthMm, heightMm)) {
pushHole({ ...spec, toolMode: spec.face === 'end' ? 'edge' : 'blind' });
}
}
if (['cotes', 'panneauxInterieurs'].includes(piece.elementType || '')) {
for (const spec of buildVerticalPanelIxconnectFaceHoleSpecsMm(piece, widthMm, heightMm)) {
pushHole({ ...spec, toolMode: spec.face === 'end' ? 'edge' : 'blind' });
}
for (const spec of buildDrawerRenfortPanelIxconnectSpecsMm(piece, widthMm, heightMm, partIndex)) {
pushHole({ ...spec, toolMode: spec.face === 'end' ? 'edge' : 'blind' });
}
}
if (['cotes', 'habillageFinitionGauche', 'habillageFinitionDroite', 'habillageFinitionDessus'].includes(piece.elementType || '')) {
for (const spec of buildFinishHabillageHoleSpecsMm(piece, widthMm, heightMm)) {
pushHole({ ...spec, toolMode: 'blind' });
}
}
if (piece.elementType === 'etageres' || piece.elementType === 'rayonFixe') {
for (const spec of buildShelfMobileHoleSpecsMm(piece, widthMm, heightMm)) {
pushHole({ ...spec, toolMode: spec.face === 'end' ? 'edge' : 'blind' });
}
}
if (piece.elementType === 'renfortsTiroir') {
for (const spec of buildDrawerReinforcementHoleSpecsMm(piece, widthMm, heightMm)) {
pushHole({ ...spec, toolMode: 'blind' });
}
}
if (piece.elementType === 'portes') {
for (const spec of buildDoorHingeCupHoleSpecsMm(piece, widthMm, heightMm)) {
pushHole({ ...spec, toolMode: 'blind', face: 'face' });
}
}
if (m.reinforcementFixing) {
const rf = m.reinforcementFixing;
const dIx = Number(rf.edgeHole?.diameter || 8);
const dT = Number(rf.tourillonDiameter || 8);
const zIx = Number(rf.edgeHole?.depth || 45);
const zT = Number(piece.thicknessMm || 16);
const yFromTop = (mm) => clampY(heightMm - Number(mm));
for (const end of ['left', 'right']) {
const xEnd = end === 'left' ? 0 : widthMm;
if (Number.isFinite(Number(rf.ixconnectAxisFromTopMm))) {
pushHole({
xMm: clampX(xEnd),
yMm: yFromTop(rf.ixconnectAxisFromTopMm),
diameterMm: dIx,
depthMm: zIx,
type: 'ixconnect',
face: 'end',
end,
toolMode: 'edge'
});
}
for (const a of rf.tourillonAxesFromTopMm || []) {
pushHole({
xMm: clampX(xEnd),
yMm: yFromTop(a),
diameterMm: dT,
depthMm: zT,
type: 'tourillon',
face: 'end',
end,
toolMode: 'edge'
});
}
}
}
return { specs, thicknessMm };
}