fix lathe preview lerp, gpu lathe end point, and index issues

This commit is contained in:
Stewart Allen 2025-12-09 00:21:26 -05:00
commit ad86c38d97
5 changed files with 37 additions and 48 deletions

View file

@ -25,12 +25,11 @@ export class OpIndex extends CamOp {
} }
prepare(ops, progress) { prepare(ops, progress) {
let { zmax, zsafe, camOut, printPoint } = ops; let { camOut, printPoint, zSafe } = ops;
// max point of stock corner radius when rotating (safe z when indexing) // max point of stock corner radius when rotating (safe z when indexing)
let ztop = Math.max(zsafe, zmax);
// move above rotating stock // move above rotating stock
camOut(printPoint = printPoint.clone().setZ(ztop), 0); camOut(printPoint = printPoint.clone().setZ(zSafe), 0);
// issue rotation command // issue rotation command
camOut(printPoint = printPoint.clone().setZ(ztop).setA(this.degrees), 0); camOut(printPoint = printPoint.clone().setZ(zSafe).setA(this.degrees), 0);
} }
} }

View file

@ -55,12 +55,14 @@ class OpLathe extends CamOp {
prepare(ops, progress) { prepare(ops, progress) {
let { op, slices, topo } = this; let { op, slices, topo } = this;
let { camOut, newLayer, zSafe } = ops; let { camOut, getLastPoint, newLayer, setContouring, setNextIsMove, zSafe } = ops;
let rez = topo.resolution; let rez = topo.resolution;
// start top center, X = 0, Y = 0 closest to 4th axis chuck // start top center, X = 0, Y = 0 closest to 4th axis chuck
camOut(newPoint(0, 0, zSafe), 0); camOut(newPoint(0, 0, zSafe).setA(0), 0);
setContouring(true);
setNextIsMove();
for (let slice of slices) { for (let slice of slices) {
// ignore debug slices // ignore debug slices
@ -68,27 +70,9 @@ class OpLathe extends CamOp {
continue; continue;
} }
let last;
for (let path of slice.camLines) { for (let path of slice.camLines) {
let latent; for (let point of path.points) {
path.forEachPoint((point, pidx) => { camOut(point);
if (last) {
const dz = Math.abs(last.z - point.z);
if (dz < rez) {
// latent point should still be included in
// preview b/c arcs would look like straight lines
latent = point.clone();
return;
}
if (latent) {
camOut(latent, 1);
latent = undefined;
}
}
camOut(last = point.clone(), pidx > 0 ? 1 : 0);
}, false);
if (latent) {
camOut(latent, 1);
} }
} }
@ -96,10 +80,8 @@ class OpLathe extends CamOp {
} }
// move to safe height and reset A axis // move to safe height and reset A axis
let last = ops.lastPoint(); let last = getLastPoint();
let amax = (Math.round(last.a / 360) * 360).round(2); let amax = (Math.round(last.a / 360) * 360).round(2);
// camOut(last = last.clone().setZ(zmax), 0);
// camOut(last = last.clone().setA(amax), 0);
newLayer(); newLayer();
ops.addGCode([`G0 Z${zSafe.round(2)}`, `G0 A${amax}`, "G92 A0"]); ops.addGCode([`G0 Z${zSafe.round(2)}`, `G0 A${amax}`, "G92 A0"]);
} }

View file

@ -178,7 +178,7 @@ export async function prepare_one(widget, settings, print, firstPoint, update) {
return tool; return tool;
} }
function setTool(toolID, feed, plunge) { function setTool(toolID, feed = camFastFeed, plunge = camFastFeedZ) {
if (toolID !== lastTool) { if (toolID !== lastTool) {
tool = new Tool(settings, toolID); tool = new Tool(settings, toolID);
toolType = tool.getType(); toolType = tool.getType();
@ -273,11 +273,13 @@ export async function prepare_one(widget, settings, print, firstPoint, update) {
function layerPush(point, emit, speed, tool, options) { function layerPush(point, emit, speed, tool, options) {
const { type, center } = options ?? {}; const { type, center } = options ?? {};
if (debug_push && options?.type !== 'lerp') { if (debug_push && options?.type !== 'lerp') {
let rounded = [point.x,point.y,point.z,point.a??0].map(v => v.toFixed(3));
if (rounded.filter(v => isNaN(v)).length) console.trace('NaN');
console.log( console.log(
currentOp.type, currentOp.type,
emit | 0, emit | 0,
speed | 0, speed | 0,
...[point.x,point.y,point.z,point.a??0].map(v => v.toFixed(3)) ...rounded
); );
} }
layerOut.mode = currentOp; layerOut.mode = currentOp;
@ -347,6 +349,8 @@ export async function prepare_one(widget, settings, print, firstPoint, update) {
p.y - wmy, p.y - wmy,
p.z - wmz p.z - wmz
) )
.setA(p.a)
.annotate({ slice: p.slice });
} }
/** /**
@ -355,7 +359,6 @@ export async function prepare_one(widget, settings, print, firstPoint, update) {
* @param {-1|0|1|2|3} emit ignore, G0, G1, G2, G3 * @param {-1|0|1|2|3} emit ignore, G0, G1, G2, G3
* @param {number} opts.shortCut used to convert short moves to cuts * @param {number} opts.shortCut used to convert short moves to cuts
* @param {number} opts.factor speed scale factor * @param {number} opts.factor speed scale factor
* @param {Object} opts.center arc center parameter
* @return {Point} translated emitted point * @return {Point} translated emitted point
*/ */
function camOut(point, emit = 1, opts) { function camOut(point, emit = 1, opts) {
@ -370,7 +373,6 @@ export async function prepare_one(widget, settings, print, firstPoint, update) {
feed = feedRate, feed = feedRate,
shortCut = toolDiamMove, shortCut = toolDiamMove,
moveOnly = false, moveOnly = false,
center,
} = opts ?? {}; } = opts ?? {};
let pointA = point.a; let pointA = point.a;
let rate = feed * factor; let rate = feed * factor;
@ -395,20 +397,25 @@ export async function prepare_one(widget, settings, print, firstPoint, update) {
// carry rotation forward when not overridden // carry rotation forward when not overridden
if (pointA !== undefined && printPoint.a !== undefined) { if (pointA !== undefined && printPoint.a !== undefined) {
let DA = printPoint.a - pointA; let DA = point.a - printPoint.a;
let MZ = Math.max(printPoint.z, point.z) let MaxZ = Math.max(printPoint.z, point.z);
// find rotary arc length // find rotary arc length
let AL = (Math.abs(DA) / 360) * (2 * Math.PI * MZ); let arcLen = (Math.abs(DA) / 360) * (2 * Math.PI * MaxZ);
if (AL >= 1) { let steps = Math.ceil(arcLen);
// emit interpolated points between printPoint and point
if (steps > 2) {
// if (point.a === 0 || printPoint.a === 0) console.log({ from: printPoint.clone(), to: point.clone() });
let zStep = (point.z - printPoint.z) / steps;
let aStep = DA / steps;
let lp = printPoint.clone();
newLayer(); newLayer();
let lerp = base.util.lerp(printPoint.a, pointA, 1);
// create interpolated point set for rendering and animation // create interpolated point set for rendering and animation
if (debug) console.log({ DA, MZ, AL }, lerp.length); while (--steps > 0) {
for (let a of lerp) { lp.z += zStep;
let lp = point.clone().setA(a); lp.a += aStep;
if (debug) console.log(lp.a, lp.x, lp.y, lp.z); // if (false)
layerPush( layerPush(
lp, lp.clone(),
emit, emit,
rate, rate,
tool, tool,
@ -424,7 +431,6 @@ export async function prepare_one(widget, settings, print, firstPoint, update) {
deltaZ = point.z - printPoint.z, deltaZ = point.z - printPoint.z,
absDeltaZ = Math.abs(deltaZ), absDeltaZ = Math.abs(deltaZ),
isMove = (emit === 0 || emit === false), isMove = (emit === 0 || emit === false),
isArc = (emit > 1),
upAndOver = false; upAndOver = false;
// contouring logic // contouring logic
@ -534,8 +540,7 @@ export async function prepare_one(widget, settings, print, firstPoint, update) {
point, point,
emit, emit,
rate, rate,
tool, tool
isArc ? { center: toWorkCoords(center) } : undefined
); );
return point; return point;
@ -834,6 +839,7 @@ export async function prepare_one(widget, settings, print, firstPoint, update) {
depthOutlinePath, depthOutlinePath,
emitDrills, emitDrills,
emitTraces, emitTraces,
getLastPoint() { return toWidgetCoords(printPoint) },
getTool, getTool,
newLayer, newLayer,
pocket, pocket,
@ -875,7 +881,7 @@ export async function prepare_one(widget, settings, print, firstPoint, update) {
newLayer(cop); newLayer(cop);
setTolerance(0); setTolerance(0);
setNextIsMove(); setNextIsMove();
if (cop.tool) setTool(cop.tool, cop.rate ?? feedRate, cop.plunge ?? plungeRate); if (cop.tool) setTool(cop.tool, cop.rate || feedRate, cop.plunge || plungeRate);
if (cop.spindle) setSpindle(cop.spindle); if (cop.spindle) setSpindle(cop.spindle);
// set printPoint in widget coordinate space // set printPoint in widget coordinate space
ops.printPoint = printPoint.clone().move({ x: -wmx, y: -wmy, z: -wmz }); ops.printPoint = printPoint.clone().move({ x: -wmx, y: -wmy, z: -wmz });

View file

@ -271,7 +271,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
if (isIndexed) { if (isIndexed) {
// preface op list with OpIndex // preface op list with OpIndex
if (activeOps.length === 0 || activeOps[0].type !== 'index') { if (activeOps.length === 0 || activeOps[0].type !== 'index') {
opList.push(new OPS.index(state, { type: "index", index: 0 })); opList.push(new OPS.index(state, { type: "index", degrees: 0, absolute: true }));
opTot += opList.peek().weight(); opTot += opList.peek().weight();
} }
@ -551,6 +551,7 @@ export function cylinder_poly_find(widget, face) {
if (!poly) throw "slicing returned no poly"; if (!poly) throw "slicing returned no poly";
let circular = poly.circularity() > 0.98; let circular = poly.circularity() > 0.98;
// console.log({ zmid, cylVerts, opts, poly, circularity: poly.circularity() });
//throw error if not circular //throw error if not circular
if (!circular) throw "faces must be circular"; if (!circular) throw "faces must be circular";

View file

@ -233,6 +233,7 @@ export class Topo {
for (let i=0; i<pointsPerLine; i++) { for (let i=0; i<pointsPerLine; i++) {
let slice = newSlice(i); let slice = newSlice(i);
let points = rows.map(row => row[i]); let points = rows.map(row => row[i]);
points.push(points[0].clone().setA(-360));
if (i % 2 === 1) points.reverse(); if (i % 2 === 1) points.reverse();
slice.index = i; slice.index = i;
slice.camLines = [ newPolygon(points).setOpen() ]; slice.camLines = [ newPolygon(points).setOpen() ];