grid-apps-cmms/src/kiri/mode/cam/op-contour.js
Stewart Allen 46c135ba23 fix tab reference for mirror op
add box area constraint for contour ops
2025-10-12 16:01:38 -04:00

178 lines
No EOL
6.7 KiB
JavaScript

/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
import { CamOp } from './op.js';
import { Tool } from './tool.js';
import { generate as Topo } from './topo3.js';
import { newPoint } from '../../../geo/point.js';
import { newPolygon } from '../../../geo/polygon.js';
import { tip2tipEmit } from '../../../geo/paths.js';
function createFilter(op, origin, axis) {
console.log({ origin, axis });
let ok = () => true;
let filter = slices => slices;
let filterString = op.filter?.map(l => l.trim()).join('\n');
if (filterString) {
try {
const obj = eval(`( ${filterString} )`);
let box = obj?.box;
let slice_fn = obj?.slices;
let index = 0;
const accept = [];
filter = function (slices) {
for (let slice of slices) {
if (slice_fn && slice_fn(slice, index++)) {
accept.push(slice);
} else if (box) {
// slice.z = x when axis = y
// slice.z = y when axis = x
let { x, y, z } = box;
x = x ?? [ -Infinity, Infinity ];
y = y ?? [ -Infinity, Infinity ];
z = z ?? [ -Infinity, Infinity ];
let ok = false;
if (axis === 'x') {
let sy = slice.z + origin.y;
if (sy >= y[0] && sy <= y[1]) {
ok = true;
for (let p of slice.camLines) {
p.points = p.points.filter(p =>
p.x - origin.x >= x[0] && p.x - origin.x <= x[1] &&
p.z - origin.z >= z[0] && p.z - origin.z <= z[1]
);
}
}
} else {
let sx = slice.z - origin.x;
if (sx >= x[0] && sx <= x[1]) {
ok = true;
for (let p of slice.camLines) {
p.points = p.points.filter(p =>
p.y + origin.y >= y[0] && p.y + origin.y <= y[1] &&
p.z - origin.z >= z[0] && p.z - origin.z <= z[1]
);
}
}
}
if (ok) {
slice.camLines = slice.camLines.map(p => {
if (p.points.length > 1) {
return newPolygon(p.points).setOpen(true);
} else {
return undefined;
}
}).filter(p => p);
accept.push(slice);
}
}
}
return accept;
};
} catch (e) {
console.log('filter parse error', e, op.filter);
}
}
return filter;
}
class OpContour extends CamOp {
constructor(state, op) {
super(state, op);
}
async slice(progress) {
let { op, state } = this;
let { color, addSlices, settings, updateToolDiams } = state;
let filter = createFilter(op, settings.origin, op.axis.toLowerCase());
let toolDiam = this.toolDiam = new Tool(settings, op.tool).fluteDiameter();
updateToolDiams(toolDiam);
// we need topo for safe travel moves when roughing and outlining
// not generated when drilling-only. then all z moves use bounds max.
// also generates x and y contouring when selected
let topo = await Topo({
// onupdate: (update, msg) => {
onupdate: (index, total, msg) => {
progress(index / total, msg);
},
ondone: (slices) => {
slices = filter(slices);
this.sliceOut = slices;
addSlices(slices);
for (let slice of slices) {
slice.output()
.setLayer(`contour ${op.axis}`, { face: color, line: color })
.addPolys(slice.camLines);
}
},
contour: op,
state: state
});
// computed if set to 0
this.tolerance = topo.tolerance;
}
prepare(ops, progress) {
let { op, state, sliceOut } = this;
let { settings, widget } = state;
let { process } = settings;
let { setTolerance, setTool, setSpindle, setPrintPoint } = ops;
let { camOut, polyEmit, newLayer, printPoint, lastPoint } = ops;
let { bounds, zmax } = ops;
let toolDiam = this.toolDiam;
let stepover = toolDiam * op.step * 2;
let depthFirst = process.camDepthFirst;
let depthData = [];
setTool(op.tool, op.rate, process.camFastFeedZ);
setSpindle(op.spindle);
setTolerance(this.tolerance);
printPoint = newPoint(bounds.min.x, bounds.min.y, zmax);
for (let slice of sliceOut) {
// ignore debug slices
if (!slice.camLines) {
continue;
}
let polys = [], poly, emit;
slice.camLines.forEach(function (poly) {
if (depthFirst) poly = poly.clone(true);
polys.push({ first: poly.first(), last: poly.last(), poly: poly });
});
if (depthFirst) {
depthData.appendAll(polys);
} else {
printPoint = tip2tipEmit(polys, printPoint, function (el, point, count) {
poly = el.poly;
if (poly.last() === point) {
poly.reverse();
}
poly.forEachPoint(function (point, pidx) {
camOut(point.clone(), pidx > 0, stepover);
}, false);
});
newLayer();
}
}
if (depthFirst) {
printPoint = tip2tipEmit(depthData, printPoint, function (el, point, count) {
let poly = el.poly;
if (poly.last() === point) {
poly.reverse();
}
poly.forEachPoint(function (point, pidx) {
camOut(point.clone(), pidx > 0, stepover);
}, false);
newLayer();
return lastPoint();
});
}
setPrintPoint(printPoint);
}
}
export { OpContour };