first pass refactor of cnc path routing
This commit is contained in:
parent
b73a25bed1
commit
f46bcc06f1
13 changed files with 286 additions and 341 deletions
|
|
@ -287,7 +287,7 @@ export function opRender() {
|
|||
oplist.forEach((rec, i) => {
|
||||
let title = '';
|
||||
let clock = rec.type === '|';
|
||||
let label = clock ? `` : rec.mode ?? rec.type;
|
||||
let label = clock ? `` : (rec.mode ? rec.type + ' ' + rec.mode : rec.type);
|
||||
let clazz = notime ? ["draggable", "notime"] : ["draggable"];
|
||||
let notable = rec.note ? rec.note.split(' ').filter(v => v.charAt(0) === '#') : undefined;
|
||||
if (clock) { clazz.push('clock'); title = ` title="end of ops chain\ndrag/drop like an op\nops after this are disabled"` }
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ class OpContour extends CamOp {
|
|||
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.
|
||||
|
|
@ -107,6 +108,7 @@ class OpContour extends CamOp {
|
|||
contour: op,
|
||||
state: state
|
||||
});
|
||||
|
||||
// computed if set to 0
|
||||
this.tolerance = topo.tolerance;
|
||||
}
|
||||
|
|
@ -116,10 +118,10 @@ class OpContour extends CamOp {
|
|||
let { settings } = state;
|
||||
let { process } = settings;
|
||||
|
||||
let { setTolerance, setTool, setSpindle, setPrintPoint } = ops;
|
||||
let { camOut, newLayer, printPoint, lastPoint } = ops;
|
||||
let { bounds, zmax } = ops;
|
||||
let { setTolerance, setTool, setSpindle } = ops;
|
||||
let { widget, camOut, newLayer, zmax } = ops;
|
||||
|
||||
let bounds = widget.getBoundingBox();
|
||||
let toolDiam = this.toolDiam;
|
||||
let stepover = toolDiam * op.step * 2;
|
||||
let depthFirst = process.camDepthFirst;
|
||||
|
|
@ -129,7 +131,7 @@ class OpContour extends CamOp {
|
|||
setSpindle(op.spindle);
|
||||
setTolerance(this.tolerance);
|
||||
|
||||
printPoint = newPoint(bounds.min.x, bounds.min.y, zmax);
|
||||
let printPoint = newPoint(bounds.min.x, bounds.min.y, zmax);
|
||||
|
||||
for (let slice of sliceOut) {
|
||||
// ignore debug slices
|
||||
|
|
@ -158,20 +160,17 @@ class OpContour extends CamOp {
|
|||
}
|
||||
|
||||
if (depthFirst) {
|
||||
printPoint = tip2tipEmit(depthData, printPoint, function (el, point, count) {
|
||||
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().annotate({ slice: poly.slice }), pidx > 0, { moveLen: stepover });
|
||||
camOut(printPoint = point.clone().annotate({ slice: poly.slice }), pidx > 0, { moveLen: stepover });
|
||||
}, false);
|
||||
newLayer();
|
||||
return lastPoint();
|
||||
});
|
||||
}
|
||||
|
||||
setPrintPoint(printPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,38 +29,42 @@ class OpDrill extends CamOp {
|
|||
if (!drill.selected) {
|
||||
return
|
||||
}
|
||||
|
||||
let slice = newSlice(0);
|
||||
if (op.mark) {
|
||||
// replace depth with single down peck
|
||||
drill.depth = op.down
|
||||
}
|
||||
|
||||
drill.zBottom = drill.z - drill.depth;
|
||||
// for thru holes, follow z thru when set
|
||||
if ((op.thru > 0)) {
|
||||
drill.zBottom -= op.thru;
|
||||
}
|
||||
|
||||
const poly = newPolygon()
|
||||
poly.points.push(newPoint(drill.x, drill.y, drill.z))
|
||||
poly.points.push(newPoint(drill.x, drill.y, drill.zBottom))
|
||||
// poly.points.pop();
|
||||
|
||||
slice.camTrace = { tool: op.tool, rate: op.feed, plunge: op.rate };
|
||||
slice.camLines = [poly];
|
||||
|
||||
slice.output()
|
||||
.setLayer(state.layername, { face: color, line: color })
|
||||
.addPolys(slice.camLines);
|
||||
|
||||
addSlices(slice);
|
||||
sliceOut.push(slice);
|
||||
});
|
||||
}
|
||||
|
||||
prepare(ops, progress) {
|
||||
let { op } = this;
|
||||
let { op, sliceOut } = this;
|
||||
let { setTool, setSpindle, setDrill, emitDrills } = ops;
|
||||
|
||||
setTool(op.tool, undefined, op.rate);
|
||||
setDrill(op.down, op.lift, op.dwell);
|
||||
setSpindle(op.spindle);
|
||||
emitDrills(this.sliceOut.map(slice => slice.camLines).flat());
|
||||
emitDrills(sliceOut.map(slice => slice.camLines).flat());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -240,20 +240,13 @@ export class OpHelical extends CamOp {
|
|||
}
|
||||
|
||||
async prepare(ops, progress) {
|
||||
let {
|
||||
setTool,
|
||||
setSpindle,
|
||||
polyEmit,
|
||||
setPrintPoint,
|
||||
getPrintPoint,
|
||||
} = ops;
|
||||
let { polyEmit, printPoint, setTool, setSpindle } = ops;
|
||||
let { tool, spindle, rate, feed } = this.op;
|
||||
|
||||
setTool(tool, feed, rate);
|
||||
setSpindle(spindle);
|
||||
|
||||
let [polys] = this.sliceOut.map((s) => s.camLines);
|
||||
let pp = getPrintPoint();
|
||||
let [ polys ] = this.sliceOut.map((s) => s.camLines);
|
||||
polys = polys.slice();
|
||||
|
||||
for (;;) {
|
||||
|
|
@ -265,7 +258,7 @@ export class OpHelical extends CamOp {
|
|||
|
||||
for (let i = 0; i < polys.length; i++) {
|
||||
if (!polys[i]) continue;
|
||||
if ((dist = polys[i].first().distTo2D(pp)) < closestDist) {
|
||||
if ((dist = polys[i].first().distTo2D(printPoint)) < closestDist) {
|
||||
closestDist = dist;
|
||||
closest = polys[i];
|
||||
closestI = i;
|
||||
|
|
@ -275,9 +268,7 @@ export class OpHelical extends CamOp {
|
|||
if (!closest) break;
|
||||
poly = polys[closestI]
|
||||
polys[closestI] = null;
|
||||
pp = polyEmit(poly, 0, 1, poly.points[0])
|
||||
printPoint = polyEmit(poly, 0, 1, poly.points[0])
|
||||
}
|
||||
|
||||
setPrintPoint(pp);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,16 +25,12 @@ export class OpIndex extends CamOp {
|
|||
}
|
||||
|
||||
prepare(ops, progress) {
|
||||
const { lastPoint, zmax, zclear, camOut, stock, newLayer } = ops;
|
||||
let last = lastPoint();
|
||||
if (last) {
|
||||
// max point of stock corner radius when rotating (safe z when indexing)
|
||||
const rzmax = (Math.max(stock.y, stock.z) * Math.sqrt(2)) / 2 + zclear;
|
||||
const zmove = Math.max(rzmax, zmax);
|
||||
// move above rotating stock
|
||||
camOut(last = last.clone().setZ(zmove), 0);
|
||||
// issue rotation command
|
||||
camOut(last = last.clone().setZ(zmove).setA(this.degrees), 0);
|
||||
}
|
||||
const { zmax, zsafe, camOut } = ops;
|
||||
// max point of stock corner radius when rotating (safe z when indexing)
|
||||
const ztop = Math.max(zsafe, zmax);
|
||||
// move above rotating stock
|
||||
camOut(last = last.clone().setZ(ztop), 0);
|
||||
// issue rotation command
|
||||
camOut(last = last.clone().setZ(ztop).setA(this.degrees), 0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class OpLathe extends CamOp {
|
|||
let { op, state, slices, topo } = this;
|
||||
let { settings } = state;
|
||||
|
||||
let { setTool, setSpindle, setPrintPoint } = ops;
|
||||
let { setTool, setSpindle } = ops;
|
||||
let { camOut, newLayer, printPoint } = ops;
|
||||
let { zmax } = ops;
|
||||
|
||||
|
|
@ -111,8 +111,6 @@ class OpLathe extends CamOp {
|
|||
// camOut(last = last.clone().setA(amax), 0);
|
||||
newLayer();
|
||||
ops.addGCode([`G0 Z${zmax.round(2)}`, `G0 A${amax}`, "G92 A0"]);
|
||||
|
||||
setPrintPoint(last);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ class OpLevel extends CamOp {
|
|||
|
||||
async slice(progress) {
|
||||
let { op, state } = this;
|
||||
let { settings, addSlices, updateToolDiams } = state;
|
||||
let { zMax, ztOff, color, tshadow } = state;
|
||||
let { addSlices, color, settings, tshadow, updateToolDiams, zMax, ztOff } = state;
|
||||
let { stock } = settings;
|
||||
|
||||
let toolDiam = new Tool(settings, op.tool).fluteDiameter();
|
||||
let stepOver = this.stepOver = toolDiam * op.step;
|
||||
let wpos = state.widget.track.pos;
|
||||
let zTop = zMax + ztOff;
|
||||
let zBot = zTop - op.down;
|
||||
let zList = op.stepz ? util.lerp(zTop, zBot, op.stepz) : [ zBot ];
|
||||
|
|
@ -28,7 +28,7 @@ class OpLevel extends CamOp {
|
|||
|
||||
let points = [];
|
||||
let clear = op.stock ?
|
||||
[ newPolygon().centerRectangle({x:0,y:0,z:0}, stock.x + toolDiam/2, stock.y) ] :
|
||||
[ newPolygon().centerRectangle({x:-wpos.x,y:-wpos.y,z:wpos.z}, stock.x + toolDiam/2, stock.y) ] :
|
||||
POLY.outer(POLY.offset(tshadow, toolDiam * (op.inset || 0)));
|
||||
|
||||
POLY.fillArea(clear, 1090, stepOver, points);
|
||||
|
|
@ -50,7 +50,7 @@ class OpLevel extends CamOp {
|
|||
|
||||
prepare(ops, progress) {
|
||||
let { op, layers, stepOver } = this;
|
||||
let { setTool, setSpindle, printPoint, setPrintPoint } = ops;
|
||||
let { setTool, setSpindle, printPoint } = ops;
|
||||
let { newLayer, tip2tipEmit, camOut } = ops;
|
||||
|
||||
setTool(op.tool, op.rate);
|
||||
|
|
@ -68,7 +68,6 @@ class OpLevel extends CamOp {
|
|||
});
|
||||
newLayer();
|
||||
}
|
||||
setPrintPoint(printPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -231,24 +231,22 @@ class OpOutline extends CamOp {
|
|||
|
||||
prepare(ops, progress) {
|
||||
let { op, state, sliceOut } = this;
|
||||
let { setTool, setSpindle, setPrintPoint } = ops;
|
||||
let { polyEmit, depthOutlinePath } = ops;
|
||||
let { newLayer, printPoint } = ops;
|
||||
let { settings } = state;
|
||||
let { process } = settings;
|
||||
let { depthOutlinePath, newLayer, polyEmit, printPoint, setTool, setSpindle } = ops;
|
||||
|
||||
let easeDown = process.camEaseDown;
|
||||
let toolDiam = this.toolDiam;
|
||||
let cutdir = op.ov_conv;
|
||||
let depthFirst = process.camDepthFirst;
|
||||
let depthData = [];
|
||||
let easeDown = process.camEaseDown;
|
||||
let toolDiam = this.toolDiam;
|
||||
|
||||
setTool(op.tool, op.rate, op.plunge);
|
||||
setSpindle(op.spindle);
|
||||
|
||||
// printpoint becomes NaN in engine mode. not sure why but this fixes it
|
||||
if(Object.values(printPoint).some(v=>Number.isNaN(v))){
|
||||
printPoint = newPoint(0,0,0);
|
||||
// printPoint becomes NaN in engine mode
|
||||
if (Object.values(printPoint).some(v => Number.isNaN(v))) {
|
||||
printPoint = newPoint(0, 0, 0);
|
||||
}
|
||||
|
||||
for (let slice of sliceOut) {
|
||||
|
|
@ -308,8 +306,6 @@ class OpOutline extends CamOp {
|
|||
printPoint = depthOutlinePath(printPoint, 0, flatLevels, toolDiam, polyEmit, true, ease);
|
||||
}
|
||||
}
|
||||
|
||||
setPrintPoint(printPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ class OpPocket extends CamOp {
|
|||
|
||||
prepare(ops, progress) {
|
||||
let { op, state, pockets } = this;
|
||||
let { getPrintPoint , pocket, setTool, setSpindle, setTolerance } = ops;
|
||||
let { pocket, setTool, setSpindle, setTolerance } = ops;
|
||||
let { process } = state.settings;
|
||||
|
||||
setTool(op.tool, op.rate);
|
||||
|
|
@ -255,36 +255,15 @@ class OpPocket extends CamOp {
|
|||
// eliminate empty pockets
|
||||
pockets = pockets.filter(p => p.length);
|
||||
|
||||
// pockets is an [ array of an [ array of slices ] ]
|
||||
// each top level array is a pocket containing a [ z layer array of slices ]
|
||||
// follow each pocket to the next closest one from previous exit
|
||||
for (;;) {
|
||||
let printPoint = getPrintPoint();
|
||||
let min = {
|
||||
dist: Infinity,
|
||||
pocket: undefined
|
||||
};
|
||||
for (let pocket of pockets.filter(p => !p.used)) {
|
||||
let poly = pocket[0].camLines.slice().sort((a,b) => b.area() - a.area())[0];
|
||||
if (!poly) continue;
|
||||
let find = poly.findClosestPointTo(printPoint);
|
||||
if (find.distance < min.dist) {
|
||||
min.pocket = pocket;
|
||||
min.dist = find.distance;
|
||||
}
|
||||
}
|
||||
if (min.pocket) {
|
||||
min.pocket.used = true;
|
||||
pocket({
|
||||
cutdir: op.ov_conv,
|
||||
depthFirst: process.camDepthFirst && !state.isIndexed,
|
||||
easeDown: op.down && process.easeDown ? op.down : 0,
|
||||
progress: (n,m) => progress(n/m, "pocket"),
|
||||
slices: min.pocket
|
||||
});
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
// naive output order
|
||||
for (let slices of pockets) {
|
||||
pocket({
|
||||
cutdir: op.ov_conv,
|
||||
depthFirst: process.camDepthFirst && !state.isIndexed,
|
||||
easeDown: op.down && process.easeDown ? op.down : 0,
|
||||
progress: (n,m) => progress(n/m, "pocket"),
|
||||
slices
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class OpRegister extends CamOp {
|
|||
|
||||
async slice(progress) {
|
||||
let { op, state } = this;
|
||||
let { settings, widget, bounds, addSlices, zMax, zThru, color } = state;
|
||||
let { addSlices, bounds, color, settings, widget, zThru } = state;
|
||||
let { updateToolDiams } = state;
|
||||
|
||||
let tool = new Tool(settings, op.tool);
|
||||
|
|
@ -23,21 +23,22 @@ class OpRegister extends CamOp {
|
|||
|
||||
updateToolDiams(tool.fluteDiameter());
|
||||
|
||||
let { stock } = settings,
|
||||
toolZ = widget.track.pos.z,
|
||||
boundMinX = bounds.min.x,
|
||||
boundMaxX = bounds.max.x,
|
||||
boundMinY = bounds.min.y,
|
||||
boundMaxY = bounds.max.y,
|
||||
toolOffset = tool.fluteDiameter() * 2,
|
||||
centerX = (boundMinX + boundMaxX) / 2,
|
||||
centerY = (boundMinY + boundMaxY) / 2,
|
||||
cutDepth = op.thru || zThru || 0,
|
||||
pathPoints = [],
|
||||
stockToSurfaceOffset = stock.z - bounds.max.z,
|
||||
startZ = bounds.max.z + stockToSurfaceOffset + toolZ,
|
||||
endZ = toolZ - cutDepth,
|
||||
cutOffset = op.offset;
|
||||
let { stock } = settings;
|
||||
let { pos } = widget.track;
|
||||
let toolZ = pos.z,
|
||||
boundMinX = bounds.min.x,
|
||||
boundMaxX = bounds.max.x,
|
||||
boundMinY = bounds.min.y,
|
||||
boundMaxY = bounds.max.y,
|
||||
toolOffset = tool.fluteDiameter() * 2,
|
||||
centerX = (boundMinX + boundMaxX) / 2,
|
||||
centerY = (boundMinY + boundMaxY) / 2,
|
||||
cutDepth = op.thru || zThru || 0,
|
||||
pathPoints = [],
|
||||
stockToSurfaceOffset = stock.z - bounds.max.z,
|
||||
startZ = bounds.max.z + stockToSurfaceOffset + toolZ,
|
||||
endZ = toolZ - cutDepth,
|
||||
cutOffset = op.offset;
|
||||
|
||||
if (!(stock.x && stock.y && stock.z)) {
|
||||
return;
|
||||
|
|
@ -146,7 +147,7 @@ class OpRegister extends CamOp {
|
|||
|
||||
prepare(ops, progress) {
|
||||
let { op } = this;
|
||||
let { setTool, setSpindle, setDrill, emitDrills } = ops;
|
||||
let { emitDrills, setDrill, setSpindle, setTool } = ops;
|
||||
|
||||
if (op.axis === '-' || op.axis === '=') {
|
||||
setTool(op.tool, op.feed, op.rate);
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ class OpRough extends CamOp {
|
|||
|
||||
prepare(ops, progress) {
|
||||
let { op, state, sliceOut, camFaces } = this;
|
||||
let { setTool, setSpindle, setPrintPoint, pocket, polyEmit, newLayer, printPoint } = ops;
|
||||
let { setTool, setSpindle, pocket, polyEmit, newLayer, printPoint } = ops;
|
||||
let { settings } = state;
|
||||
let { process } = settings;
|
||||
|
||||
|
|
@ -329,7 +329,6 @@ class OpRough extends CamOp {
|
|||
}
|
||||
|
||||
// output the roughing passes
|
||||
setPrintPoint(printPoint);
|
||||
pocket({
|
||||
cutdir,
|
||||
depthFirst,
|
||||
|
|
|
|||
|
|
@ -18,28 +18,44 @@ const { toRadians } = util
|
|||
* @param {Number} [index] into widget array
|
||||
* @param {Object} [firstPoint] starting point
|
||||
*/
|
||||
export async function cam_prepare(widall, settings, update) {
|
||||
const widgets = widall.filter(w => !w.track.ignore && !w.meta.disabled);
|
||||
const count = widgets.length;
|
||||
export async function cam_prepare(widgets, settings, update) {
|
||||
const active = widgets
|
||||
.filter(w => !w.isSynth() && !w.track.ignore && !w.meta.disabled)
|
||||
.filter(w => w?.camops.length)
|
||||
;
|
||||
const count = active.length;
|
||||
const weight = 1 / count;
|
||||
const print = self.kiri_worker.current.print = newPrint(settings, widgets);
|
||||
const print = self.kiri_worker.current.print = newPrint(settings, active);
|
||||
const { origin } = settings;
|
||||
|
||||
// cam-specific storage
|
||||
print.output = [];
|
||||
|
||||
let point;
|
||||
widgets.filter(w => !w.isSynth()).forEach((widget, index) => {
|
||||
point = prepEach(widget, settings, print, point, (progress, msg) => {
|
||||
// sort output by distance to origin
|
||||
if (origin) {
|
||||
let point = newPoint().move(origin);
|
||||
active.sort((w0,w1) =>
|
||||
newPoint().move(w0.track.pos).distTo2D(point) -
|
||||
newPoint().move(w1.track.pos).distTo2D(point)
|
||||
);
|
||||
}
|
||||
|
||||
let startPoint;
|
||||
active.forEach((widget, index) => {
|
||||
startPoint = prepare_one(widget, settings, print, startPoint, (progress, msg) => {
|
||||
update((index * weight + progress * weight) * 0.75, msg || "prepare");
|
||||
});
|
||||
});
|
||||
|
||||
// prune empty levels
|
||||
const output = print.output.filter(level => Array.isArray(level));
|
||||
|
||||
if (render) // allows it to run from CLI
|
||||
return render.path(
|
||||
output,
|
||||
(progress, layer) => {
|
||||
update(0.75 + progress * 0.25, "render", layer);
|
||||
}, {
|
||||
// compute path display
|
||||
return render.path(
|
||||
output,
|
||||
(progress, layer) => {
|
||||
update(0.75 + progress * 0.25, "render", layer);
|
||||
}, {
|
||||
thin: true,
|
||||
print: 0,
|
||||
move: 0x557799,
|
||||
|
|
@ -49,82 +65,75 @@ export async function cam_prepare(widall, settings, update) {
|
|||
action: "milling",
|
||||
maxspeed: settings.process.camFastFeed || 6000
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
export function prepEach(widget, settings, print, firstPoint, update) {
|
||||
|
||||
if (widget.camops.length === 0 || widget.meta.disabled) return;
|
||||
// process `prepare` paths for a single widget
|
||||
export function prepare_one(widget, settings, print, firstPoint, update) {
|
||||
|
||||
let { device, process } = settings,
|
||||
isIndexed = process.camStockIndexed,
|
||||
startCenter = process.camOriginCenter,
|
||||
alignTop = settings.controller.alignTop,
|
||||
{ alignTop } = settings.controller,
|
||||
{ camArcEnabled, camArcResolution, camArcTolerance } = process,
|
||||
{ camDepthFirst, camEaseAngle, camEaseDown } = process,
|
||||
{ camForceZMax, camFullEngage, camInnerFirst, camOriginCenter } = process,
|
||||
{ camOriginOffX, camOriginOffY, camOriginOffZ } = process,
|
||||
{ camStockOffset, camStockIndexed, camZClearance } = process,
|
||||
stock = settings.stock || {},
|
||||
stockz = stock.z * (isIndexed ? 0.5 : 1),
|
||||
outer = settings.bounds || widget.getPositionBox(),
|
||||
outerz = outer.max.z,
|
||||
zclear = (process.camZClearance || 1),
|
||||
zmax_force = process.camForceZMax || false,
|
||||
zmax_outer = stockz + zclear,
|
||||
wztop = widget.track.top,
|
||||
ztOff = stockz - wztop,
|
||||
stockZ = stock.z * (camStockIndexed ? 0.5 : 1),
|
||||
outer = settings.bounds || widget.getPositionBox(), // dup of bounds?
|
||||
outerZ = outer.max.z, // dup of boundsZ?
|
||||
stockZClear = stockZ + camZClearance,
|
||||
widgetTrackTop = widget.track.top,
|
||||
widgetTopToStock = stockZ - widgetTrackTop,
|
||||
bounds = widget.getBoundingBox(),
|
||||
boundsz = isIndexed ? stock.z / 2 : bounds.max.z + ztOff,
|
||||
zadd = !isIndexed ? stock.z - boundsz : alignTop ? outerz - boundsz : 0,
|
||||
zmax = outerz + zclear + (process.camOriginOffZ || 0),
|
||||
zsafe = isIndexed ? Math.hypot(bounds.dim.y, bounds.dim.z) / 2 + zclear : zmax,
|
||||
boundsZ = camStockIndexed ? stock.z / 2 : bounds.max.z + widgetTopToStock,
|
||||
zMax = outerZ + camZClearance + (camOriginOffZ || 0) + widgetTopToStock,
|
||||
zSafe = camStockIndexed ? Math.hypot(bounds.dim.y, bounds.dim.z) / 2 + camZClearance : zMax,
|
||||
wmpos = widget.track.pos,
|
||||
wmx = wmpos.x,
|
||||
wmy = wmpos.y,
|
||||
originx = (startCenter ? 0 : -stock.x / 2) + (process.camOriginOffX || 0),
|
||||
originy = (startCenter ? 0 : -stock.y / 2) + (process.camOriginOffY || 0),
|
||||
origin = newPoint(originx + wmx, originy + wmy, zmax),
|
||||
easeDown = process.camEaseDown,
|
||||
easeAngle = process.camEaseAngle,
|
||||
depthFirst = process.camDepthFirst,
|
||||
innerFirst = process.camInnerFirst,
|
||||
engageFactor = process.camFullEngage,
|
||||
arcTolerance = process.camArcTolerance,
|
||||
arcRes = toRadians(process.camArcResolution),
|
||||
arcEnabled = process.camArcEnabled && arcTolerance > 0 && arcRes > 0,
|
||||
tolerance = 0,
|
||||
wmz = !camStockIndexed ? stock.z - boundsZ : alignTop ? outerZ - boundsZ : 0,
|
||||
originx = (camOriginCenter ? 0 : -stock.x / 2) + (camOriginOffX || 0),
|
||||
originy = (camOriginCenter ? 0 : -stock.y / 2) + (camOriginOffY || 0),
|
||||
origin = newPoint(originx, originy, zMax),
|
||||
arcRadians = toRadians(camArcResolution),
|
||||
arcEnabled = camArcEnabled && camArcTolerance > 0 && arcRadians > 0,
|
||||
currentOp,
|
||||
drillDown = 0,
|
||||
drillLift = 0,
|
||||
drillDwell = 0,
|
||||
lasering = false,
|
||||
laserPower = 0,
|
||||
newOutput = print.output || [],
|
||||
layerOut = [],
|
||||
printPoint,
|
||||
feedRate,
|
||||
isPocket,
|
||||
isContour,
|
||||
isRough,
|
||||
isLathe,
|
||||
isIndex,
|
||||
layerOut = [],
|
||||
lastOp,
|
||||
lastTool,
|
||||
lastPush,
|
||||
lasering = false,
|
||||
laserPower = 0,
|
||||
maxToolDiam = widget.maxToolDiam,
|
||||
newOutput = print.output || [],
|
||||
plungeRate = process.camFastFeedZ,
|
||||
printPoint,
|
||||
tool,
|
||||
toolType,
|
||||
toolDiam,
|
||||
toolDiamMove,
|
||||
plungeRate = process.camFastFeedZ,
|
||||
feedRate,
|
||||
lastOp,
|
||||
lastTool,
|
||||
lastPush,
|
||||
lastPoint,
|
||||
currentOp,
|
||||
nextIsMove = true,
|
||||
synthPlunge = false,
|
||||
spindle = 0,
|
||||
spindleMax = device.spindleMax,
|
||||
maxToolDiam = widget.maxToolDiam,
|
||||
terrain = widget.terrain ? widget.terrain.map(data => {
|
||||
return {
|
||||
z: data.z,
|
||||
tops: data.tops,
|
||||
};
|
||||
}) : zmax;
|
||||
|
||||
}) : zMax,
|
||||
tolerance = 0;
|
||||
console.log({ zSafe, stockZ, outerZ, boundsZ, wmz });
|
||||
function newLayer(op) {
|
||||
if (layerOut.length || layerOut.mode) {
|
||||
newOutput.push(layerOut);
|
||||
|
|
@ -158,10 +167,6 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
}
|
||||
}
|
||||
|
||||
function setPrintPoint(point) {
|
||||
ops.printPoint = printPoint = point;
|
||||
}
|
||||
|
||||
function setSpindle(speed) {
|
||||
spindle = Math.min(speed, spindleMax);
|
||||
}
|
||||
|
|
@ -209,7 +214,6 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
|
||||
if (!closest) return;
|
||||
polys[closestI] = null;
|
||||
printPoint = closest.first();
|
||||
emitDrill(closest, drillDown, drillLift, drillDwell);
|
||||
}
|
||||
}
|
||||
|
|
@ -240,7 +244,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
camOut(point.clone().setZ(zmax_outer), 0);
|
||||
camOut(point.clone().setZ(stockZClear), 0);
|
||||
points.forEach(function (point, index) {
|
||||
camOut(point, 1);
|
||||
if (index > 0 && index < points.length - 1) {
|
||||
|
|
@ -248,7 +252,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
if (lift) camOut(point.clone().setZ(point.z + lift), 0);
|
||||
}
|
||||
})
|
||||
camOut(point.clone().setZ(zmax_outer), 0);
|
||||
camOut(point.clone().setZ(stockZClear), 0);
|
||||
newLayer();
|
||||
}
|
||||
|
||||
|
|
@ -270,7 +274,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
let power = emit ? laserPower : 0;
|
||||
if (emit && lasering.adapt) {
|
||||
let { minz, maxz, minp, maxp, adaptrp } = lasering;
|
||||
maxz = maxz || wztop;
|
||||
maxz = maxz || widgetTrackTop;
|
||||
let deltaz = maxz - minz;
|
||||
let { z } = point;
|
||||
if (adaptrp) {
|
||||
|
|
@ -288,13 +292,14 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
}
|
||||
}
|
||||
if (lasering.flat) {
|
||||
point.z = (stock && stock.z ? stock.z : wztop) + lasering.flatz;
|
||||
point.z = (stock && stock.z ? stock.z : widgetTrackTop) + lasering.flatz;
|
||||
}
|
||||
print.addOutput(layerOut, point, power, speed, tool, { type: 'laser' });
|
||||
} else {
|
||||
print.addOutput(layerOut, point, emit, speed, tool, { type, center, arcPoints });
|
||||
}
|
||||
lastPush = { point, emit, speed, tool };
|
||||
printPoint = point ?? printPoint;
|
||||
return point;
|
||||
}
|
||||
|
||||
|
|
@ -316,8 +321,17 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
return newPoint(
|
||||
p.x + wmx,
|
||||
p.y + wmy,
|
||||
p.z + zadd
|
||||
).setA(p.a ?? lastPoint?.a).annotate({ slice: p.slice });
|
||||
p.z + wmz
|
||||
)
|
||||
.setA(p.a ?? printPoint?.a)
|
||||
.annotate({ slice: p.slice });
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapper: translate point into workspace coordinates and call `camOut`
|
||||
*/
|
||||
function camOut(point, emit = 1, opts) {
|
||||
_camOut(applyWidgetMovement(point), emit, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -329,7 +343,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
* @param {number} opts.moveLen typically = tool diameter used to trigger terrain detection
|
||||
* @param {number} opts.factor speed scale factor
|
||||
*/
|
||||
function camOut(point, emit = 1, opts) {
|
||||
function _camOut(point, emit, opts) {
|
||||
let lop = lastOp;
|
||||
lastOp = currentOp;
|
||||
|
||||
|
|
@ -337,17 +351,15 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
// 1. move to safe z of current point preserving angle
|
||||
// 2. move to safe z of new point preserving old angle
|
||||
// 3. move to safe z of new point with new angle
|
||||
if (lop !== currentOp && lastPoint) {
|
||||
// compensate for applyWidgetMovement() applied to lastPoint
|
||||
let lpo = lastPoint.clone().move({ x: -wmx, y: -wmy, z: -zadd });
|
||||
camOut(lpo.clone().setZ(zsafe).setA(lastPoint.a), 0);
|
||||
camOut(point.clone().setZ(zsafe).setA(lastPoint.a), 0);
|
||||
camOut(point.clone().setZ(zsafe), 0);
|
||||
if (lop !== currentOp) {
|
||||
_camOut(printPoint.clone().setZ(zSafe).setA(printPoint.a), 0);
|
||||
_camOut(point.clone().setZ(zSafe).setA(printPoint.a), 0);
|
||||
_camOut(point.clone().setZ(zSafe), 0);
|
||||
}
|
||||
|
||||
if (lop?.type === 'index' && lop !== currentOp ) {
|
||||
// console.log('post index first point', point);
|
||||
camOut(point.clone().setZ(lastPoint.z).setA(lastPoint.a), 1);
|
||||
_camOut(point.clone().setZ(printPoint.z).setA(printPoint.a), 1);
|
||||
}
|
||||
|
||||
let {
|
||||
|
|
@ -361,9 +373,6 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
const isArc = emit == 2 || emit == 3;
|
||||
const pointA = point.a;
|
||||
|
||||
// apply widget movement pos
|
||||
point = applyWidgetMovement(point);
|
||||
|
||||
if (nextIsMove) {
|
||||
emit = 0;
|
||||
nextIsMove = false;
|
||||
|
|
@ -372,13 +381,13 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
let rate = feedRate * factor;
|
||||
|
||||
// carry rotation forward when not overridden
|
||||
if (lastPoint && pointA !== undefined && lastPoint.a !== undefined) {
|
||||
let DA = lastPoint.a - pointA;
|
||||
let MZ = Math.max(lastPoint.z, point.z)
|
||||
if (pointA !== undefined && printPoint.a !== undefined) {
|
||||
let DA = printPoint.a - pointA;
|
||||
let MZ = Math.max(printPoint.z, point.z)
|
||||
// find arc length
|
||||
let AL = (Math.abs(DA) / 360) * (2 * Math.PI * MZ);
|
||||
if (AL >= 1) {
|
||||
let lerp = base.util.lerp(lastPoint.a, pointA, 1);
|
||||
let lerp = base.util.lerp(printPoint.a, pointA, 1);
|
||||
// create interpolated point set for rendering and animation
|
||||
// console.log({ DA, MZ, AL }, lerp.length);
|
||||
for (let a of lerp) {
|
||||
|
|
@ -395,39 +404,31 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
}
|
||||
}
|
||||
|
||||
// before first point, move cutting head to point above it
|
||||
// then set that new point as the lastPoint
|
||||
if (!lastPoint) {
|
||||
let above = point.clone().setZ(stockz + zclear);
|
||||
// let above = point.clone().setZ(zmax + zadd + ztOff);
|
||||
lastPoint = layerPush(above, 0, 0, tool);
|
||||
}
|
||||
|
||||
// measure deltas to last point in XY and Z
|
||||
let deltaXY = lastPoint.distTo2D(point),
|
||||
deltaZ = point.z - lastPoint.z,
|
||||
let deltaXY = printPoint.distTo2D(point),
|
||||
deltaZ = point.z - printPoint.z,
|
||||
absDeltaZ = Math.abs(deltaZ),
|
||||
hasDelta = deltaXY >= 0.001 && absDeltaZ >= 0,
|
||||
isMove = emit == 0;
|
||||
|
||||
// when rapid pluge could cut thru stock, rapid to just above stock
|
||||
// then continue plunge as a plunge cut
|
||||
if (deltaZ < 0 && lastPoint.z > stockz && point.z < stockz && emit === 0) {
|
||||
// console.log('detected plunge cut as rapid move', lastPoint.z, stockz, point.z);
|
||||
layerPush(point.clone().setZ(stockz + 1), 0, 0, tool);
|
||||
if (deltaZ < 0 && printPoint.z > stockZ && point.z < stockZ && emit === 0) {
|
||||
// console.log('detected plunge cut as rapid move', printPoint.z, stockZ, point.z);
|
||||
layerPush(point.clone().setZ(stockZ + 1), 0, 0, tool);
|
||||
// change to cutting move for remainder of plunge
|
||||
emit = 1;
|
||||
isMove = false;
|
||||
}
|
||||
|
||||
// drop points too close together
|
||||
if (!isLathe && !isArc && deltaXY < 0.001 && point.z === lastPoint.z && point.a === lastPoint.a) {
|
||||
// console.trace(["drop dup",lastPoint,point]);
|
||||
if (!isLathe && !isArc && deltaXY < 0.001 && point.z === printPoint.z && point.a === printPoint.a) {
|
||||
// console.trace(["drop dup",printPoint,point]);
|
||||
return;
|
||||
}
|
||||
|
||||
// no jump moves in contour mode to adjacent slice points
|
||||
let steady = lastPoint && currentOp.type === 'contour' && Math.abs(point.slice - lastPoint.slice) < 4;
|
||||
let steady = currentOp.type === 'contour' && Math.abs(point.slice - printPoint.slice) < 4;
|
||||
|
||||
// convert short planar moves to cuts in some cases
|
||||
if (hasDelta && !isArc && isMove && deltaXY <= moveLen && deltaZ <= 0 && !lasering) {
|
||||
|
|
@ -439,15 +440,15 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
isMove = false;
|
||||
} else if (deltaZ <= -tolerance) {
|
||||
// move over before descending
|
||||
layerPush(point.clone().setZ(lastPoint.z), 0, 0, tool);
|
||||
layerPush(point.clone().setZ(printPoint.z), 0, 0, tool);
|
||||
// new pos for plunge calc
|
||||
deltaXY = 0;
|
||||
}
|
||||
} else if (isMove && isLathe) {
|
||||
if (point.z > lastPoint.z) {
|
||||
layerPush(lastPoint.clone().setZ(point.z), 0, 0, tool);
|
||||
} else if (point.z < lastPoint.z) {
|
||||
layerPush(point.clone().setZ(lastPoint.z), 0, 0, tool);
|
||||
if (point.z > printPoint.z) {
|
||||
layerPush(printPoint.clone().setZ(point.z), 0, 0, tool);
|
||||
} else if (point.z < printPoint.z) {
|
||||
layerPush(point.clone().setZ(printPoint.z), 0, 0, tool);
|
||||
}
|
||||
} else if (isMove && !steady) {
|
||||
// for longer moves, check the terrain to see if we need to go up and over
|
||||
|
|
@ -458,40 +459,40 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
if (bigXY || bigZ || midZ) {
|
||||
let maxz = getZClearPath(
|
||||
terrain,
|
||||
lastPoint.x - wmx,
|
||||
lastPoint.y - wmy,
|
||||
point.x - wmx,
|
||||
point.y - wmy,
|
||||
Math.max(point.z, lastPoint.z),
|
||||
zadd,
|
||||
printPoint.x,
|
||||
printPoint.y,
|
||||
point.x,
|
||||
point.y,
|
||||
Math.max(point.z, printPoint.z),
|
||||
0, // zadd,
|
||||
maxToolDiam / 2,
|
||||
zclear
|
||||
camZClearance
|
||||
),
|
||||
maxZdelta = Math.max(maxz - point.z, maxz - lastPoint.z),
|
||||
maxZdelta = Math.max(maxz - point.z, maxz - printPoint.z),
|
||||
mustGoUp = maxZdelta >= tolerance,
|
||||
clearz = maxz;
|
||||
let zIsBelow = point.z <= maxz;
|
||||
if (zmax_force) {
|
||||
clearz = maxz = zmax + zadd;
|
||||
if (camForceZMax) {
|
||||
clearz = maxz = zMax;// + zadd;
|
||||
zIsBelow = true;
|
||||
}
|
||||
// up if any point between higher than start/outline, go up first
|
||||
if (mustGoUp || zIsBelow) {
|
||||
const zClearance = clearz + (isIndexed ? 0 : ztOff);
|
||||
const zClearance = clearz + (camStockIndexed ? 0 : widgetTopToStock);
|
||||
if (zIsBelow) {
|
||||
layerPush(lastPoint.clone().setZ(zClearance), 0, 0, tool);
|
||||
layerPush(printPoint.clone().setZ(zClearance), 0, 0, tool);
|
||||
}
|
||||
layerPush(point.clone().setZ(zClearance), 0, 0, tool);
|
||||
// new pos for plunge calc
|
||||
deltaXY = 0;
|
||||
// if plunge goes below stock, convert to cut
|
||||
if (emit === 0 && point.z < stockz) {
|
||||
lastPoint = layerPush(point.clone().setZ(stockz + 1), 0, 0, tool);
|
||||
if (emit === 0 && point.z < stockZ) {
|
||||
layerPush(point.clone().setZ(stockZ + 1), 0, 0, tool);
|
||||
emit = 1;
|
||||
}
|
||||
}
|
||||
} else if (isRough && deltaZ < 0) {
|
||||
layerPush(point.clone().setZ(lastPoint.z), 0, 0, tool);
|
||||
layerPush(point.clone().setZ(printPoint.z), 0, 0, tool);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -526,7 +527,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
if (isArc) {
|
||||
layerOut.mode = currentOp;
|
||||
layerOut.spindle = spindle;
|
||||
lastPoint = layerPush(
|
||||
layerPush(
|
||||
point,
|
||||
clockwise ? 2 : 3,
|
||||
tmprate ?? rate,
|
||||
|
|
@ -541,7 +542,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
// TODO: synthesize move speed from feed / plunge accordingly
|
||||
layerOut.mode = currentOp;
|
||||
layerOut.spindle = spindle;
|
||||
lastPoint = layerPush(
|
||||
layerPush(
|
||||
point,
|
||||
emit,
|
||||
tmprate ?? rate,
|
||||
|
|
@ -581,10 +582,10 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
depthData.push(polys);
|
||||
} else {
|
||||
// if not depth first, output the polys in slice order
|
||||
printPoint = poly2polyEmit(polys, printPoint, function (poly, index, count) {
|
||||
poly2polyEmit(polys, printPoint, function (poly, index, count) {
|
||||
poly.forEachPoint(function (point, pidx, points, offset) {
|
||||
// scale speed of first cutting poly since it engages the full bit
|
||||
camOut(point.clone(), offset !== 0, undefined, count === 1 ? engageFactor : 1);
|
||||
camOut(point.clone(), offset !== 0, undefined, count === 1 ? camFullEngage : 1);
|
||||
}, poly.isClosed(), index);
|
||||
}, { swapdir: false });
|
||||
newLayer();
|
||||
|
|
@ -608,8 +609,8 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
let otops = outs.map(level => {
|
||||
return POLY.nest(level.filter(poly => poly.depth === 0).clone());
|
||||
});
|
||||
printPoint = depthRoughPath(printPoint, 0, ins, itops, polyEmit, false, easeDown);
|
||||
printPoint = depthRoughPath(printPoint, 0, outs, otops, polyEmit, false, easeDown);
|
||||
depthRoughPath(printPoint, 0, ins, itops, polyEmit, false, easeDown);
|
||||
depthRoughPath(printPoint, 0, outs, otops, polyEmit, false, easeDown);
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
|
@ -677,73 +678,12 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
return touch;
|
||||
}
|
||||
|
||||
// coming from a previous widget, use previous last point
|
||||
lastPoint = firstPoint;
|
||||
|
||||
// make top start offset configurable
|
||||
printPoint = firstPoint || origin;
|
||||
|
||||
let ops = {
|
||||
addGCode,
|
||||
bounds,
|
||||
camOut,
|
||||
depthOutlinePath,
|
||||
depthRoughPath,
|
||||
emitDrills,
|
||||
emitTrace,
|
||||
getPrintPoint() { return printPoint },
|
||||
lastPoint: () => { return lastPoint },
|
||||
newLayer,
|
||||
pocket,
|
||||
poly2polyEmit,
|
||||
polyEmit,
|
||||
printPoint,
|
||||
setDrill,
|
||||
setLasering,
|
||||
setPrintPoint,
|
||||
setSpindle,
|
||||
setTolerance,
|
||||
setTool,
|
||||
stock,
|
||||
tip2tipEmit,
|
||||
zclear,
|
||||
zmax,
|
||||
zsafe,
|
||||
};
|
||||
|
||||
let opSum = 0;
|
||||
let opTot = widget.camops.map(op => op.weight()).reduce((a, v) => a + v);
|
||||
|
||||
for (let op of widget.camops) {
|
||||
setTolerance(0);
|
||||
nextIsMove = true;
|
||||
currentOp = op.op;
|
||||
isIndex = currentOp.type === 'index';
|
||||
isLathe = currentOp.type === 'lathe';
|
||||
isRough = currentOp.type === 'rough';
|
||||
isPocket = currentOp.type === 'pocket';
|
||||
isContour = currentOp.type === 'contour' || (isPocket && currentOp.contour);
|
||||
let weight = op.weight();
|
||||
newLayer(op.op);
|
||||
op.prepare(ops, (progress, message) => {
|
||||
update((opSum + (progress * weight)) / opTot, message || op.type(), message);
|
||||
});
|
||||
opSum += weight;
|
||||
if (tool && lastPoint) {
|
||||
newLayer();
|
||||
if (!isIndex) {
|
||||
layerPush(printPoint = lastPoint.clone().setZ(zmax_outer), 0, 0, tool);
|
||||
newLayer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitTrace(slice) {
|
||||
let { tool, rate, plunge } = slice.camTrace;
|
||||
setTool(tool, rate, plunge);
|
||||
printPoint = poly2polyEmit(slice.camLines, printPoint, polyEmit, {
|
||||
poly2polyEmit(slice.camLines, printPoint, polyEmit, {
|
||||
swapdir: false,
|
||||
weight: innerFirst
|
||||
weight: camInnerFirst
|
||||
});
|
||||
newLayer();
|
||||
}
|
||||
|
|
@ -765,11 +705,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
* @returns {Point} - the last point of the polygon
|
||||
*/
|
||||
function polyEmit(poly, index, count, fromPoint, ops) {
|
||||
let {
|
||||
cutFromLast,
|
||||
} = ops ?? {
|
||||
cutFromLast: false
|
||||
};
|
||||
let { cutFromLast } = ops ?? { cutFromLast: false };
|
||||
let arcQ = [],
|
||||
arcMax = Infinity, // no max arc radius
|
||||
lineTolerance = 0.001, // do not consider points under 0.001mm for arcs
|
||||
|
|
@ -778,24 +714,21 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
fromPoint = fromPoint || printPoint;
|
||||
arcQ.angle = []
|
||||
|
||||
let lastPoint = fromPoint;
|
||||
let startIndex = index;
|
||||
|
||||
// console.log({poly, index, count, fromPoint, startIndex})
|
||||
|
||||
// scale speed of first cutting poly since it engages the full bit
|
||||
let scale = ((isRough || isPocket) && count === 1) ? engageFactor : 1;
|
||||
let scale = ((isRough || isPocket) && count === 1) ? camFullEngage : 1;
|
||||
let startIndex = index;
|
||||
let polyLastPoint = fromPoint;
|
||||
|
||||
// easeDown only allowed on closed polys (that we can continue around indefinitly)
|
||||
if (easeDown && poly.isClosed()) {
|
||||
if (camEaseDown && poly.isClosed()) {
|
||||
let closest = poly.findClosestPointTo(fromPoint);
|
||||
lastPoint = closest.point;
|
||||
polyLastPoint = closest.point;
|
||||
startIndex = closest.index;
|
||||
let last = generateEaseDown((point, offset) => { // generate ease-down points
|
||||
if (offset == 0) camOut(point.clone(), 0, { factor: engageFactor });
|
||||
if (offset == 0) camOut(point.clone(), 0, { factor: camFullEngage });
|
||||
camOut(point.clone(), 1, { factor: scale }); // and pass them to camOut
|
||||
}, poly, fromPoint, easeAngle);
|
||||
lastPoint = poly.points[last];
|
||||
}, poly, fromPoint, camEaseAngle);
|
||||
polyLastPoint = poly.points[last];
|
||||
startIndex = last;
|
||||
}
|
||||
|
||||
|
|
@ -806,11 +739,11 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
// console.log({pointA, pointB, indexA, indexB,startIndex})
|
||||
if (indexA == startIndex) {
|
||||
//if cutFromLast is true, emit a 1 for a cutting move
|
||||
camOut(pointA.clone(), cutFromLast ? 1 : 0, { factor: engageFactor });
|
||||
camOut(pointA.clone(), cutFromLast ? 1 : 0, { factor: camFullEngage });
|
||||
// if first point, move to and call export function
|
||||
if (arcEnabled) arcQ.push(pointA);
|
||||
}
|
||||
lastPoint = arcExport(pointB, pointA);
|
||||
polyLastPoint = arcExport(pointB, pointA);
|
||||
}, !poly.isClosed(), startIndex);
|
||||
|
||||
// console.log("at end of arcExport",structuredClone(arcQ));
|
||||
|
|
@ -844,7 +777,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
let radFault = false;
|
||||
if (lr) {
|
||||
let angle = 2 * Math.asin(dist / (2 * lr.r));
|
||||
radFault = Math.abs(angle) > arcRes; // enforce arcRes(olution)
|
||||
radFault = Math.abs(angle) > arcRadians; // enforce arcRadians(olution)
|
||||
} else {
|
||||
// console.log("too much angle")
|
||||
radFault = true;
|
||||
|
|
@ -873,10 +806,10 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
|
||||
// check if first angles should have caused radFault
|
||||
let angle = toRadians(arcQ[0].slopeTo(cc).angleDiff(arcQ[1].slopeTo(cc)).angle)
|
||||
radFault = Math.abs(angle) > arcRes
|
||||
radFault = Math.abs(angle) > arcRadians
|
||||
if (radFault) {
|
||||
// if so, remove first point
|
||||
console.log("secondary radfault,",structuredClone(arcQ),{angle,arcRes,a,b})
|
||||
console.log("secondary radfault,",structuredClone(arcQ),{angle,arcRadians,a,b})
|
||||
camOut(arcQ.shift(), 1)
|
||||
}
|
||||
|
||||
|
|
@ -891,9 +824,9 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
}
|
||||
// if new point is off the arc
|
||||
// if point is off-center, or too far from center, or too large of a radius
|
||||
if (dc * arcQ.center.length / arcQ.rSum > arcTolerance || dist > cc.r || cc.r > arcMax || radFault || zFault) {
|
||||
// let debug = [ dc * arcQ.center.length / arcQ.rSum > arcTolerance, dist > cc.r, cc.r > arcMax, radFault];
|
||||
// console.log("point off the arc,",structuredClone(arcQ),radFault,zFault,[dc * arcQ.center.length / arcQ.rSum > arcTolerance , dist > cc.r , cc.r > arcMax]);
|
||||
if (dc * arcQ.center.length / arcQ.rSum > camArcTolerance || dist > cc.r || cc.r > arcMax || radFault || zFault) {
|
||||
// let debug = [ dc * arcQ.center.length / arcQ.rSum > camArcTolerance, dist > cc.r, cc.r > arcMax, radFault];
|
||||
// console.log("point off the arc,",structuredClone(arcQ),radFault,zFault,[dc * arcQ.center.length / arcQ.rSum > camArcTolerance , dist > cc.r , cc.r > arcMax]);
|
||||
if (arcQ.length === 4) {
|
||||
// not enough points for an arc, drop first point and recalc center
|
||||
camOut(arcQ.shift(), 1);
|
||||
|
|
@ -904,7 +837,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
} else {
|
||||
arcQ.center = [tc];
|
||||
let angle = 2 * Math.asin(arcQ[1].dist / (2 * tc.r));
|
||||
if (Math.abs(angle) > arcRes) { // enforce arcRes on initial angle
|
||||
if (Math.abs(angle) > arcRadians) { // enforce arcRadians on initial angle
|
||||
camOut(arcQ.shift(), 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -949,7 +882,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
// console.trace("draining")
|
||||
let arcPreviewRes = 64
|
||||
|
||||
if (!arcTolerance) {
|
||||
if (!camArcTolerance) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -978,42 +911,36 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
// generate circle
|
||||
// console.log("circle",{from, to,center});
|
||||
to = forceCircle? from.clone().setZ(to.z) : from
|
||||
|
||||
|
||||
let arcPoints = arcToPath(from, to, arcPreviewRes, { clockwise, center })
|
||||
.map(applyWidgetMovement);
|
||||
|
||||
let arcPoints = arcToPath(from, to, arcPreviewRes, { clockwise, center });
|
||||
// console.log({arcPoints})
|
||||
|
||||
camOut(from, 1);
|
||||
camOut(to, gc, { center: center.sub(from), clockwise, arcPoints });
|
||||
} else {
|
||||
//if a non-circle arc
|
||||
let arcPoints = arcToPath(from, to, arcPreviewRes, { clockwise, center })
|
||||
.map(applyWidgetMovement);
|
||||
let arcPoints = arcToPath(from, to, arcPreviewRes, { clockwise, center });
|
||||
// console.log("arc")
|
||||
// first arc point
|
||||
camOut(from, 1);
|
||||
// rest of arc to final point
|
||||
camOut(to, gc, { center: center.sub(from), clockwise, arcPoints });
|
||||
lastPoint = to.clone();
|
||||
polyLastPoint = to.clone();
|
||||
}
|
||||
} else {
|
||||
//if q too short, emit as lines
|
||||
for (let rec of arcQ) {
|
||||
camOut(rec, 1);
|
||||
}
|
||||
lastPoint = arcQ.peek().clone();
|
||||
polyLastPoint = arcQ.peek().clone();
|
||||
}
|
||||
arcQ.length = 0;
|
||||
arcQ.center = undefined;
|
||||
}
|
||||
|
||||
if (depthFirst) {
|
||||
if (camDepthFirst) {
|
||||
newLayer();
|
||||
}
|
||||
|
||||
return lastPoint;
|
||||
return polyLastPoint;
|
||||
}
|
||||
|
||||
function depthRoughPath(start, depth, levels, tops, emitter, fit, ease) {
|
||||
|
|
@ -1093,26 +1020,82 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
|||
fromPoint = depthOutlinePath(fromPoint, depth + 1, levels, radius, emitter, !dir, ease);
|
||||
return fromPoint;
|
||||
}, {
|
||||
weight: innerFirst,
|
||||
weight: camInnerFirst,
|
||||
swapdir: false
|
||||
});
|
||||
return start;
|
||||
}
|
||||
|
||||
// last layer/move is to zmax
|
||||
// re-inject that point into the last layer generated
|
||||
if (lastPoint && newOutput.length) {
|
||||
let lastLayer = newOutput.filter(layer => Array.isArray(layer)).peek();
|
||||
if (Array.isArray(lastLayer)) {
|
||||
printPoint = lastPoint.clone();
|
||||
if (printPoint.z < zmax_outer) printPoint.setZ(zmax_outer);
|
||||
print.addOutput(lastLayer, printPoint, 0, 0, tool);
|
||||
// print.addOutput(lastLayer, printPoint = lastPoint.clone().setZ(zmax_outer), 0, 0, tool);
|
||||
console.log({ prep: widget, firstPoint: firstPoint?.clone(), wmx, wmy, printPoint, origin: origin.clone() });
|
||||
|
||||
// coming from a previous widget, use previous last point as starting point
|
||||
// make top start offset configurable
|
||||
printPoint = firstPoint || origin;
|
||||
|
||||
let ops = {
|
||||
addGCode,
|
||||
camOut,
|
||||
depthOutlinePath,
|
||||
depthRoughPath,
|
||||
emitDrills,
|
||||
emitTrace,
|
||||
newLayer,
|
||||
pocket,
|
||||
poly2polyEmit,
|
||||
polyEmit,
|
||||
printPoint,
|
||||
setDrill,
|
||||
setLasering,
|
||||
setSpindle,
|
||||
setTolerance,
|
||||
setTool,
|
||||
tip2tipEmit,
|
||||
widget,
|
||||
zMax,
|
||||
zSafe,
|
||||
};
|
||||
|
||||
let opSum = 0;
|
||||
let opTot = widget.camops.map(op => op.weight()).reduce((a, v) => a + v);
|
||||
|
||||
for (let op of widget.camops) {
|
||||
setTolerance(0);
|
||||
nextIsMove = true;
|
||||
currentOp = op.op;
|
||||
isIndex = currentOp.type === 'index';
|
||||
isLathe = currentOp.type === 'lathe';
|
||||
isRough = currentOp.type === 'rough';
|
||||
isPocket = currentOp.type === 'pocket';
|
||||
isContour = currentOp.type === 'contour' || (isPocket && currentOp.contour);
|
||||
let weight = op.weight();
|
||||
newLayer(op.op);
|
||||
op.prepare(ops, (progress, message) => {
|
||||
update((opSum + (progress * weight)) / opTot, message || op.type(), message);
|
||||
});
|
||||
opSum += weight;
|
||||
if (tool && printPoint) {
|
||||
newLayer();
|
||||
if (!isIndex) {
|
||||
layerPush(printPoint.clone().setZ(stockZClear), 0, 0, tool);
|
||||
newLayer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// last layer/move is to zMax
|
||||
// re-inject that point into the last layer generated
|
||||
if (printPoint && newOutput.length) {
|
||||
let lastLayer = newOutput.filter(layer => Array.isArray(layer)).peek();
|
||||
if (Array.isArray(lastLayer)) {
|
||||
if (printPoint.z < stockZClear) printPoint.setZ(stockZClear);
|
||||
print.addOutput(lastLayer, printPoint, 0, 0, tool);
|
||||
}
|
||||
}
|
||||
|
||||
// console.log("prepare output", newOutput);
|
||||
// replace output single flattened layer with all points
|
||||
print.output = newOutput;
|
||||
|
||||
return printPoint;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
|||
opTot += opList.peek().weight();
|
||||
}
|
||||
|
||||
// determing # of steps and step weighting for progress bar
|
||||
// determine # of steps and step weighting for progress bar
|
||||
for (let op of activeOps) {
|
||||
if (op.type === '|') {
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in a new issue