get prepare displaying G2s

This commit is contained in:
bakedpotatolord 2025-05-31 18:40:14 -06:00
commit 47e312d486
5 changed files with 139 additions and 51 deletions

View file

@ -22,6 +22,8 @@ CAM.export = function(print, online) {
const widget = print.widgets[0]; const widget = print.widgets[0];
if (!widget) return; if (!widget) return;
console.log(print);
const { settings } = print; const { settings } = print;
const { device, tools } = settings; const { device, tools } = settings;
@ -164,6 +166,7 @@ CAM.export = function(print, online) {
} }
} }
function moveTo(out, opt = {}) { function moveTo(out, opt = {}) {
let laser = out.type === 'laser'; let laser = out.type === 'laser';
let newpos = out.point; let newpos = out.point;
@ -251,18 +254,23 @@ CAM.export = function(print, online) {
points--; points--;
return; return;
} }
console.log(out)
let gn;
if ( out.emit >=0 && out.emit <= 3) gn = `G${out.emit}`;
else throw new Error(`malformed emit type ${out.emit}`);
let speed = out.speed, let speed = out.speed,
gn = speed ? 'G1' : 'G0', arc = out.emit == 2 || out.emit == 3,
nl = (compact_output && lastGn === gn) ? [] : [gn], nl = (compact_output && lastGn === gn) ? [] : [gn],
dx = opt.dx || newpos.x - pos.x, dx = opt.dx || newpos.x - pos.x,
dy = opt.dy || newpos.y - pos.y, dy = opt.dy || newpos.y - pos.y,
dz = opt.dz || newpos.z - pos.z, dz = opt.dz || newpos.z - pos.z,
da = newpos.a != pos.a, da = newpos.a != pos.a,
maxf = dz ? maxZd : maxXYd, maxf = dz ? maxZd : maxXYd,
feed = Math.min(speed || maxf, maxf), feed = Math.min(speed || maxf, maxf),
dist = Math.sqrt(dx * dx + dy * dy + dz * dz), dist = Math.sqrt(dx * dx + dy * dy + dz * dz),
newFeed = feed && feed !== pos.f; newFeed = feed && feed !== pos.f;
// drop dup points (all deltas are 0) // drop dup points (all deltas are 0)
if (!(dx || dy || dz || da)) { if (!(dx || dy || dz || da)) {

View file

@ -7,6 +7,7 @@
// dep: geo.polygons // dep: geo.polygons
// dep: kiri.render // dep: kiri.render
// dep: kiri-mode.cam.driver // dep: kiri-mode.cam.driver
// dep: kiri.print
// use: kiri-mode.cam.ops // use: kiri-mode.cam.ops
gapp.register("kiri-mode.cam.prepare", (root, exports) => { gapp.register("kiri-mode.cam.prepare", (root, exports) => {
@ -18,6 +19,7 @@ const { CAM } = driver;
const POLY = polygons; const POLY = polygons;
/** /**
* DRIVER PRINT CONTRACT * DRIVER PRINT CONTRACT
* *
@ -43,18 +45,21 @@ CAM.prepare = async function(widall, settings, update) {
const output = print.output.filter(level => Array.isArray(level)); const output = print.output.filter(level => Array.isArray(level));
if (render) // allows it to run from CLI if (render) // allows it to run from CLI
return render.path(output, (progress, layer) => { return render.path(
update(0.75 + progress * 0.25, "render", layer); output,
}, { (progress, layer) => {
thin: true, update(0.75 + progress * 0.25, "render", layer);
print: 0, }, {
move: 0x557799, thin: true,
speed: false, print: 0,
moves: true, move: 0x557799,
other: "moving", speed: false,
action: "milling", moves: true,
maxspeed: settings.process.camFastFeed || 6000 other: "moving",
}); action: "milling",
maxspeed: settings.process.camFastFeed || 6000
}
);
}; };
function prepEach(widget, settings, print, firstPoint, update) { function prepEach(widget, settings, print, firstPoint, update) {
@ -258,11 +263,12 @@ function prepEach(widget, settings, print, firstPoint, update) {
/** /**
* @param {Point} point * @param {Point} point
* @param {number} emit (0=move, !0=filament emit/laser on/cut mode) * @param {number} emit (0=move, 1=/laser on/cut mode, 2/3= G2/G3 arc)
* @param {number} [speed] feed/plunge rate in mm/min * @param {number} [speed] feed/plunge rate in mm/min
* @param {number} [tool] tool number * @param {number} [tool] tool number
*/ */
function layerPush(point, emit, speed, tool, type) { function layerPush(point, emit, speed, tool, options) {
const { type, radius, arcPoints } = options ?? {};
const dz = (point && lastPush && lastPush.point) ? point.z - lastPush.point.z : 0; const dz = (point && lastPush && lastPush.point) ? point.z - lastPush.point.z : 0;
if (dz < 0 && speed > plungeRate) { if (dz < 0 && speed > plungeRate) {
speed = plungeRate; speed = plungeRate;
@ -292,9 +298,9 @@ function prepEach(widget, settings, print, firstPoint, update) {
if (lasering.flat) { if (lasering.flat) {
point.z = (stock && stock.z ? stock.z : wztop) + lasering.flatz; point.z = (stock && stock.z ? stock.z : wztop) + lasering.flatz;
} }
print.addOutput(layerOut, point, power, speed, tool, 'laser'); print.addOutput(layerOut, point, power, speed, tool, {type:'laser'});
} else { } else {
print.addOutput(layerOut, point, emit, speed, tool, type); print.addOutput(layerOut, point, emit, speed, tool, {type, radius, arcPoints});
} }
lastPush = { point, emit, speed, tool }; lastPush = { point, emit, speed, tool };
return point; return point;
@ -321,12 +327,15 @@ function prepEach(widget, settings, print, firstPoint, update) {
function camOut(point, cut,opts) { function camOut(point, cut,opts) {
let { let {
radius = null, radius = 0,
clockwise = true, clockwise = true,
arcPoints = [],
moveLen = toolDiamMove, moveLen = toolDiamMove,
factor = 1, factor = 1,
} = opts ?? {} } = opts ?? {}
const isArc = radius > 0;
point = point.clone(); point = point.clone();
point.x += wmx; point.x += wmx;
point.y += wmy; point.y += wmy;
@ -360,7 +369,7 @@ function prepEach(widget, settings, print, firstPoint, update) {
cut ? 1 : 0, cut ? 1 : 0,
rate, rate,
tool, tool,
"lerp" {type:"lerp"},
); );
} }
} }
@ -378,7 +387,7 @@ function prepEach(widget, settings, print, firstPoint, update) {
let deltaXY = lastPoint.distTo2D(point), let deltaXY = lastPoint.distTo2D(point),
deltaZ = point.z - lastPoint.z, deltaZ = point.z - lastPoint.z,
absDeltaZ = Math.abs(deltaZ), absDeltaZ = Math.abs(deltaZ),
isMove = !cut; isMove = !(cut || isArc);
// drop points too close together // drop points too close together
if (!isLathe && deltaXY < 0.001 && point.z === lastPoint.z) { if (!isLathe && deltaXY < 0.001 && point.z === lastPoint.z) {
@ -460,15 +469,32 @@ function prepEach(widget, settings, print, firstPoint, update) {
} }
} }
// todo synthesize move speed from feed / plunge accordingly
layerOut.mode = currentOp; if(isArc) {
layerOut.spindle = spindle; console.log("arc recieved");
lastPoint = layerPush( layerPush(
point, point,
cut ? 1 : 0, clockwise ? 2 : 3,
rate, rate,
tool tool,
); {
radius,
arcPoints
}
);
}else{
// for g1 moves
// TODO: synthesize move speed from feed / plunge accordingly
layerOut.mode = currentOp;
layerOut.spindle = spindle;
lastPoint = layerPush(
point,
cut ? 1 : 0,
rate,
tool
);
}
} }
/** /**
@ -768,7 +794,7 @@ function prepEach(widget, settings, print, firstPoint, update) {
// if (deem || depm || desp || dc > arcDist || cc.r < arcMin || cc.r > arcMax || dist > cc.r) { // if (deem || depm || desp || dc > arcDist || cc.r < arcMin || cc.r > arcMax || dist > cc.r) {
if ( desp || dc * arcQ.center.length / arcQ.rSum > arcDist || dist > cc.r || cc.r > arcMax || radFault ) { if ( desp || dc * arcQ.center.length / arcQ.rSum > arcDist || dist > cc.r || cc.r > arcMax || radFault ) {
// let debug = [deem, depm, desp, dc * arcQ.center.length / arcQ.rSum > arcDist, dist > cc.r, cc.r > arcMax, radFault]; // let debug = [deem, depm, desp, dc * arcQ.center.length / arcQ.rSum > arcDist, dist > cc.r, cc.r > arcMax, radFault];
console.log("point off the arc,",structuredClone(arcQ)); // console.log("point off the arc,",structuredClone(arcQ));
if (arcQ.length === 4) { if (arcQ.length === 4) {
// not enough points for an arc, drop first point and recalc center // not enough points for an arc, drop first point and recalc center
camOut(arcQ.shift(),1); camOut(arcQ.shift(),1);
@ -856,10 +882,9 @@ function prepEach(widget, settings, print, firstPoint, update) {
// XYR form // XYR form
// let pre = `${clockwise? 'G2' : 'G3'} X${to.x.toFixed(decimals)} Y${to.y.toFixed(decimals)} R${cc.r.toFixed(decimals)} `; // let pre = `${clockwise? 'G2' : 'G3'} X${to.x.toFixed(decimals)} Y${to.y.toFixed(decimals)} R${cc.r.toFixed(decimals)} `;
camOut(to,1,{radius:cc.r, clockwise}); camOut(to,1,{radius:cc.r, clockwise, arcPoints:[...arcQ]});
// XYIJ form // XYIJ form
// let pre = `${clockwise? 'G2' : 'G3'} X${to.x.toFixed(decimals)} Y${to.y.toFixed(decimals)} I${(cc.x - pos.x).toFixed(decimals)} J${(cc.y - pos.y).toFixed(decimals)} E${emit.toFixed(decimals)}`; // let pre = `${clockwise? 'G2' : 'G3'} X${to.x.toFixed(decimals)} Y${to.y.toFixed(decimals)} I${(cc.x - pos.x).toFixed(decimals)} J${(cc.y - pos.y).toFixed(decimals)} E${emit.toFixed(decimals)}`;
// let add = pos.f !== from.speedMMM ? ` E${from.speedMMM}` : ''; // let add = pos.f !== from.speedMMM ? ` E${from.speedMMM}` : '';
// append(`${pre}${add} ; merged=${cl-1} len=${dist.toFixed(decimals)} cp=${cc.x.round(2)},${cc.y.round(2)}`); // append(`${pre}${add} ; merged=${cl-1} len=${dist.toFixed(decimals)} cp=${cc.x.round(2)},${cc.y.round(2)}`);
} else { } else {

View file

@ -739,7 +739,7 @@ FDM.prepare = async function(widgets, settings, update) {
// outside brim // outside brim
if (firstLayerBrim && !brimHalf) { if (firstLayerBrim && !brimHalf) {
print.addOutput(tmpout, newPoint(maxx + b, y, z), 0, outputSeekrate, tool); print.addOutput(tmpout, newPoint(maxx + b, y, z), 0, outputSeekrate, tool);
print.addOutput(tmpout, newPoint(maxx + g, y, z), emit, firstLayerRate, tool).retract = true; print.addOutput(tmpout, newPoint(maxx + g, y, z), emit, firstLayerRate, tool,{retract: true})
} }
// inside brim // inside brim
if (firstLayerBrimIn && pads.length > 1) { if (firstLayerBrimIn && pads.length > 1) {
@ -752,20 +752,20 @@ FDM.prepare = async function(widgets, settings, update) {
if (x1 - x0 > bi * 2) { if (x1 - x0 > bi * 2) {
// over 2x brim so emit two segments // over 2x brim so emit two segments
print.addOutput(tmpout, newPoint(x1 - g, y, z), 0, outputSeekrate, tool); print.addOutput(tmpout, newPoint(x1 - g, y, z), 0, outputSeekrate, tool);
print.addOutput(tmpout, newPoint(x1 - bi, y, z), emit, firstLayerRate, tool).retract = true; print.addOutput(tmpout, newPoint(x1 - bi, y, z), emit, firstLayerRate, tool, {retract: true});
print.addOutput(tmpout, newPoint(x0 + bi, y, z), 0, outputSeekrate, tool); print.addOutput(tmpout, newPoint(x0 + bi, y, z), 0, outputSeekrate, tool);
print.addOutput(tmpout, newPoint(x0 + g, y, z), emit, firstLayerRate, tool).retract = true; print.addOutput(tmpout, newPoint(x0 + g, y, z), emit, firstLayerRate, tool, {retract: true});
} else if (x1 - x0 > bi / 3) { } else if (x1 - x0 > bi / 3) {
// over 1/3rd brim length emit single segment // over 1/3rd brim length emit single segment
print.addOutput(tmpout, newPoint(x1 - g, y, z), 0, outputSeekrate, tool); print.addOutput(tmpout, newPoint(x1 - g, y, z), 0, outputSeekrate, tool);
print.addOutput(tmpout, newPoint(x0 + g, y, z), emit, firstLayerRate, tool).retract = true; print.addOutput(tmpout, newPoint(x0 + g, y, z), emit, firstLayerRate, tool, {retract: true});
} }
} }
} }
// outside brim // outside brim
if (firstLayerBrim) { if (firstLayerBrim) {
print.addOutput(tmpout, newPoint(minx - b, y, z), 0, outputSeekrate, tool); print.addOutput(tmpout, newPoint(minx - b, y, z), 0, outputSeekrate, tool);
print.addOutput(tmpout, newPoint(minx - g, y, z), emit, firstLayerRate, tool).retract = false; print.addOutput(tmpout, newPoint(minx - g, y, z), emit, firstLayerRate, tool, {retract: true});
} }
// when there is a printing move between layers // when there is a printing move between layers
// inject non-printing move to after brim to prevent erroneous extrusion // inject non-printing move to after brim to prevent erroneous extrusion

View file

@ -42,7 +42,8 @@ class Print {
this.widget = widget; this.widget = widget;
} }
addOutput(array, point, emit, speed, tool, type) { addOutput(array, point, emit, speed, tool, opts) {
const { type, retract, radius, arcPoints} = opts ?? {};
let { lastPoint, lastEmit, lastOut } = this; let { lastPoint, lastEmit, lastOut } = this;
// drop duplicates (usually intruced by FDM bisections) // drop duplicates (usually intruced by FDM bisections)
if (lastPoint && point && type !== 'lerp') { if (lastPoint && point && type !== 'lerp') {
@ -55,10 +56,15 @@ class Print {
// if (emit && emit < 1) console.log(emit); // if (emit && emit < 1) console.log(emit);
this.lastPoint = point; this.lastPoint = point;
this.lastEmit = emit; this.lastEmit = emit;
this.lastOut = lastOut = new Output(point, emit, speed, tool, type || this.nextType); this.lastOut = lastOut = new Output(point, emit, speed, tool, {
type: type ?? this.nextType,
radius,
arcPoints,
});
if (tool !== undefined) { if (tool !== undefined) {
this.tools[tool] = true; this.tools[tool] = true;
} }
lastOut.retract = retract;
lastOut.widget = this.widget; lastOut.widget = this.widget;
array.push(lastOut); array.push(lastOut);
this.nextType = undefined; this.nextType = undefined;
@ -554,12 +560,31 @@ class Print {
} }
class Output { class Output {
constructor(point, emit, speed, tool, type, radius) { /**
* Construct a new output element.
*
* in cam, emit is the G code number (G0, G1, G2, G3)
*
* @param {Point} point point to emit, with x, y, and z properties
* @param {number} emit emit (feed for printers, power for lasers, cut for cam)
* @param {number} speed speed in mm/min
* @param {number} tool tool id
* @param {Object} options options object
* @param {string} [options.type] type of point
* @param {number} [options.radius] radius of arc
* @param {Point[]} [options.arcPoints] point based approximation of arc
*/
constructor(point, emit, speed, tool, options) {
const { type, radius, arcPoints } = (options ?? {});
//speed, tool, type, radius
this.point = point; // point to emit this.point = point; // point to emit
this.emit = emit; // emit (feed for printers, power for lasers, cut for cam) this.emit = emit; // emit (feed for printers, power for lasers, cut for cam)
this.speed = speed; this.speed = speed;
this.tool = tool; this.tool = tool;
this.type = type; this.type = type;
this.radius = radius;
this.arcPoints = arcPoints;
// this.where = new Error().stack.split("\n"); // this.where = new Error().stack.split("\n");
} }

View file

@ -44,6 +44,13 @@ function rate_to_color(rate, max) {
} }
}; };
/**
* Generate visual representation of a gcode program.
* @param {Output[][]} levels - Array of arrays containing `Output` objects.
* @param {function} update - Called with a completion percentage and the rendered layer.
* @param {{tools: Object, flat: Boolean, thin: Boolean, speed: Boolean, lineWidth: Number, toolMode: Boolean, z: Number, action: String, other: String}} [opts] - Optional parameters.
* @returns {Promise.kiri.Layers[]} - Array of layers.
*/
async function path(levels, update, opts = {}) { async function path(levels, update, opts = {}) {
levels = levels.filter(level => level.length); levels = levels.filter(level => level.length);
if (levels.length === 0) { if (levels.length === 0) {
@ -183,7 +190,8 @@ async function path(levels, update, opts = {}) {
return; return;
} }
if (lastOut) { if (lastOut) { // if last outpoint is defined
if (arrowAll || lastOut.emit !== out.emit) { if (arrowAll || lastOut.emit !== out.emit) {
heads.push({p1: lastOutPoint, p2: outPoint}); heads.push({p1: lastOutPoint, p2: outPoint});
} }
@ -193,7 +201,29 @@ async function path(levels, update, opts = {}) {
// Math.abs(op.y - lp.y), // Math.abs(op.y - lp.y),
// Math.abs(op.z - lp.z)); // Math.abs(op.z - lp.z));
// if (moved < 0.0001) return; // if (moved < 0.0001) return;
if (out.emit) { if( is_cam() && (out.emit == 2 || out.emit == 3 )) {
// cam arc emit
console.log('cam arc render woohoo!',out);
// checks if a new poly should be started
if (!lastOut.emit || (ckspeed && out.speed !== lastOut.speed) || lastEnd) {
current = newPolygon().setOpen();
current.push(lastOutPoint);
current.color = color(out);
pushPrint(out.tool, current);
}
out.arcPoints.forEach(p => {
current.push(p);
})
current.push(outPoint);
} else if (out.emit) {
// explicity G1 in CAM mode
// just a non-move in other modes
// checks if a new poly should be started
if (!lastOut.emit || (ckspeed && out.speed !== lastOut.speed) || lastEnd) { if (!lastOut.emit || (ckspeed && out.speed !== lastOut.speed) || lastEnd) {
current = newPolygon().setOpen(); current = newPolygon().setOpen();
current.push(lastOutPoint); current.push(lastOutPoint);