checkpoint arc generation on export
This commit is contained in:
parent
3662f9b50c
commit
b23a38ce86
7 changed files with 156 additions and 8 deletions
|
|
@ -356,7 +356,7 @@
|
||||||
* return circle center given three points
|
* return circle center given three points
|
||||||
* from https://stackoverflow.com/questions/4103405/what-is-the-algorithm-for-finding-the-center-of-a-circle-from-three-points
|
* from https://stackoverflow.com/questions/4103405/what-is-the-algorithm-for-finding-the-center-of-a-circle-from-three-points
|
||||||
*/
|
*/
|
||||||
function center2d(A,B,C) {
|
function center2d(A,B,C,rad) {
|
||||||
let yDelta_a = B.y - A.y,
|
let yDelta_a = B.y - A.y,
|
||||||
xDelta_a = B.x - A.x,
|
xDelta_a = B.x - A.x,
|
||||||
yDelta_b = C.y - B.y,
|
yDelta_b = C.y - B.y,
|
||||||
|
|
@ -366,7 +366,11 @@
|
||||||
center = {x:0, y:0, z:0};
|
center = {x:0, y:0, z:0};
|
||||||
center.x = (aSlope*bSlope*(A.y - C.y) + bSlope*(A.x + B.x) - aSlope*(B.x+C.x) )/(2* (bSlope-aSlope) );
|
center.x = (aSlope*bSlope*(A.y - C.y) + bSlope*(A.x + B.x) - aSlope*(B.x+C.x) )/(2* (bSlope-aSlope) );
|
||||||
center.y = -1*(center.x - (A.x+B.x)/2)/aSlope + (A.y+B.y)/2;
|
center.y = -1*(center.x - (A.x+B.x)/2)/aSlope + (A.y+B.y)/2;
|
||||||
|
if (rad) {
|
||||||
|
let dx = center.x - A.x;
|
||||||
|
let dy = center.y - A.y;
|
||||||
|
center.r = Math.sqrt(dx*dx + dy*dy)
|
||||||
|
}
|
||||||
return center;
|
return center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -666,6 +666,16 @@
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PRO.addObj = function(obj) {
|
||||||
|
if (Array.isArray(obj)) {
|
||||||
|
for (let o of obj) {
|
||||||
|
this.addObj(o);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return this.add(obj.x, obj.y, obj.z);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* append array of points to polygon and return polygon
|
* append array of points to polygon and return polygon
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -343,6 +343,7 @@
|
||||||
sliceMinHeight: 0,
|
sliceMinHeight: 0,
|
||||||
sliceAdaptive: false,
|
sliceAdaptive: false,
|
||||||
zHopDistance: 0.2,
|
zHopDistance: 0.2,
|
||||||
|
arcTolerance: 0,
|
||||||
antiBacklash: 1,
|
antiBacklash: 1,
|
||||||
gcodePause: ""
|
gcodePause: ""
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1783,6 +1783,7 @@
|
||||||
outputCoastDist: UC.newInput(LANG.ad_scst_s, {title:LANG.ad_scst_l, bound:UC.bound(0.0,10), convert:UC.toFloat, modes:FDM}),
|
outputCoastDist: UC.newInput(LANG.ad_scst_s, {title:LANG.ad_scst_l, bound:UC.bound(0.0,10), convert:UC.toFloat, modes:FDM}),
|
||||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||||
zHopDistance: UC.newInput(LANG.ad_zhop_s, {title:LANG.ad_zhop_l, bound:UC.bound(0,3.0), convert:UC.toFloat, modes:FDM}),
|
zHopDistance: UC.newInput(LANG.ad_zhop_s, {title:LANG.ad_zhop_l, bound:UC.bound(0,3.0), convert:UC.toFloat, modes:FDM}),
|
||||||
|
arcTolerance: UC.newInput(LANG.ad_arct_s, {title:LANG.ad_arct_l, bound:UC.bound(0,1.0), convert:UC.toFloat, modes:FDM, show:isNotBelt}),
|
||||||
antiBacklash: UC.newInput(LANG.ad_abkl_s, {title:LANG.ad_abkl_l, bound:UC.bound(0,3), convert:UC.toInt, modes:FDM}),
|
antiBacklash: UC.newInput(LANG.ad_abkl_s, {title:LANG.ad_abkl_l, bound:UC.bound(0,3), convert:UC.toInt, modes:FDM}),
|
||||||
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
fdmSep: UC.newBlank({class:"pop-sep", modes:FDM}),
|
||||||
gcodePauseLayers: UC.newInput(LANG.ag_paws_s, {title:LANG.ag_paws_l, modes:FDM, comma:true}),
|
gcodePauseLayers: UC.newInput(LANG.ag_paws_s, {title:LANG.ag_paws_l, modes:FDM, comma:true}),
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,20 @@
|
||||||
const beltaxis = { X: "X", Y: "Z", Z: "Y", E: "E", F: "F" };
|
const beltaxis = { X: "X", Y: "Z", Z: "Y", E: "E", F: "F" };
|
||||||
const beltfact = Math.cos(Math.PI/4);
|
const beltfact = Math.cos(Math.PI/4);
|
||||||
|
|
||||||
|
function G2G3(g2, line) {
|
||||||
|
const rec = {};
|
||||||
|
|
||||||
|
line.forEach(function(tok) {
|
||||||
|
rec[tok.charAt(0)] = parseFloat(tok.substring(1));
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log({g2, arc: line, pos});
|
||||||
|
|
||||||
|
pos.X = rec.X;
|
||||||
|
pos.Y = rec.Y;
|
||||||
|
pos.Z = rec.Z;
|
||||||
|
}
|
||||||
|
|
||||||
function G0G1(g0, line) {
|
function G0G1(g0, line) {
|
||||||
const mov = {};
|
const mov = {};
|
||||||
|
|
||||||
|
|
@ -284,6 +298,14 @@
|
||||||
case 'G1':
|
case 'G1':
|
||||||
G0G1(false, line);
|
G0G1(false, line);
|
||||||
break;
|
break;
|
||||||
|
case 'G2':
|
||||||
|
// turn arc into a series of points
|
||||||
|
G2G3(true, line)
|
||||||
|
break;
|
||||||
|
case 'G3':
|
||||||
|
// turn arc into a series of points
|
||||||
|
G2G3(false, line);
|
||||||
|
break;
|
||||||
case 'M6':
|
case 'M6':
|
||||||
tool = parseInt(line[0].substring(1));
|
tool = parseInt(line[0].substring(1));
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
pause = [],
|
pause = [],
|
||||||
pauseCmd = device.gcodePause,
|
pauseCmd = device.gcodePause,
|
||||||
output = [],
|
output = [],
|
||||||
outputLength = 0,
|
outputLength = 0, // absolute extruder position
|
||||||
lastProgress = 0,
|
lastProgress = 0,
|
||||||
decimals = BASE.config.gcode_decimals || 4,
|
decimals = BASE.config.gcode_decimals || 4,
|
||||||
progress = 0,
|
progress = 0,
|
||||||
|
|
@ -50,6 +50,7 @@
|
||||||
retSpeed = process.outputRetractSpeed * 60,
|
retSpeed = process.outputRetractSpeed * 60,
|
||||||
retDwell = process.outputRetractDwell || 0,
|
retDwell = process.outputRetractDwell || 0,
|
||||||
timeDwell = retDwell / 1000,
|
timeDwell = retDwell / 1000,
|
||||||
|
arcDist = isBelt ? 0 : (process.arcTolerance || 0),
|
||||||
originCenter = process.outputOriginCenter,
|
originCenter = process.outputOriginCenter,
|
||||||
offset = originCenter ? null : {
|
offset = originCenter ? null : {
|
||||||
x: device.bedWidth/2,
|
x: device.bedWidth/2,
|
||||||
|
|
@ -80,7 +81,9 @@
|
||||||
bcos = Math.cos(Math.PI/4),
|
bcos = Math.cos(Math.PI/4),
|
||||||
icos = 1 / bcos,
|
icos = 1 / bcos,
|
||||||
loops = process.outputLoopLayers,
|
loops = process.outputLoopLayers,
|
||||||
inLoop;
|
inLoop,
|
||||||
|
arcAt,
|
||||||
|
arcQ = [];
|
||||||
|
|
||||||
if (isBelt && loops) {
|
if (isBelt && loops) {
|
||||||
loops = loops.split(',').map(range => {
|
loops = loops.split(',').map(range => {
|
||||||
|
|
@ -392,6 +395,7 @@
|
||||||
|
|
||||||
// re-engage post-retraction before new extrusion
|
// re-engage post-retraction before new extrusion
|
||||||
if (out.emit && retracted) {
|
if (out.emit && retracted) {
|
||||||
|
drainQ();
|
||||||
// console.log({engage:zhop});
|
// console.log({engage:zhop});
|
||||||
// when enabled, resume previous Z
|
// when enabled, resume previous Z
|
||||||
if (zhop && pos.z != zpos) moveTo({z:zpos}, seekMMM, "z-hop end");
|
if (zhop && pos.z != zpos) moveTo({z:zpos}, seekMMM, "z-hop end");
|
||||||
|
|
@ -404,10 +408,58 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastp && out.emit) {
|
if (lastp && out.emit) {
|
||||||
|
if (arcDist) {
|
||||||
|
let rec = {e:out.emit, x, y, z, dist, emitPerMM, speedMMM};
|
||||||
|
arcQ.push(rec);
|
||||||
|
let deem = false;
|
||||||
|
let depm = false;
|
||||||
|
let desp = false;
|
||||||
|
if (arcQ.length > 1) {
|
||||||
|
deem = arcQ[0].e !== rec.e;
|
||||||
|
depm = arcQ[0].emitPerMM !== rec.emitPerMM;
|
||||||
|
desp = arcQ[0].speedMMM !== rec.speedMMM;
|
||||||
|
}
|
||||||
|
if (arcQ.length > 2) {
|
||||||
|
let el = arcQ.length;
|
||||||
|
let e1 = arcQ[el-3];
|
||||||
|
let e2 = arcQ[el-2];
|
||||||
|
let e3 = arcQ[el-1];
|
||||||
|
let cc = BASE.util.center2d(e1, e2, e3, 1);
|
||||||
|
let dc = 0;
|
||||||
|
if (arcQ.length === 3) {
|
||||||
|
arcQ.center = [ cc ];
|
||||||
|
} else {
|
||||||
|
// check center point delta
|
||||||
|
let dx = cc.x - arcQ.center[0].x;
|
||||||
|
let dy = cc.y - arcQ.center[0].y;
|
||||||
|
dc = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
}
|
||||||
|
// if new point is off the arc
|
||||||
|
if (deem || depm || desp || dc > arcDist) {
|
||||||
|
// console.log({dc, depm, desp});
|
||||||
|
if (arcQ.length === 4) {
|
||||||
|
// not enough points for an arc, drop first point and recalc center
|
||||||
|
emitQrec(arcQ.shift());
|
||||||
|
arcQ.center = [ BASE.util.center2d(arcQ[0], arcQ[1], arcQ[2], 1) ];
|
||||||
|
} else {
|
||||||
|
// enough to consider an arc, emit and start new arc
|
||||||
|
let defer = arcQ.pop();
|
||||||
|
drainQ();
|
||||||
|
// re-add point that was off the last arc
|
||||||
|
arcQ.push(defer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// new point is on the arc
|
||||||
|
arcQ.center.push(cc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
emitMM = emitPerMM * out.emit * dist;
|
emitMM = emitPerMM * out.emit * dist;
|
||||||
moveTo({x:x, y:y, e:emitMM}, speedMMM);
|
moveTo({x:x, y:y, e:emitMM}, speedMMM);
|
||||||
emitted += emitMM;
|
emitted += emitMM;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
drainQ();
|
||||||
moveTo({x:x, y:y}, seekMMM);
|
moveTo({x:x, y:y}, seekMMM);
|
||||||
// TODO disabling out of plane z moves until a better mechanism
|
// TODO disabling out of plane z moves until a better mechanism
|
||||||
// can be built that doesn't rely on computed zpos from layer heights...
|
// can be built that doesn't rely on computed zpos from layer heights...
|
||||||
|
|
@ -418,6 +470,7 @@
|
||||||
|
|
||||||
// retract filament if point retract flag set
|
// retract filament if point retract flag set
|
||||||
if (out.retract) {
|
if (out.retract) {
|
||||||
|
drainQ();
|
||||||
retract(zhop);
|
retract(zhop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -437,6 +490,61 @@
|
||||||
}
|
}
|
||||||
layer++;
|
layer++;
|
||||||
}
|
}
|
||||||
|
drainQ();
|
||||||
|
|
||||||
|
function emitQrec(rec) {
|
||||||
|
let {e, x, y, dist, emitPerMM, speedMMM} = rec;
|
||||||
|
emitMM = emitPerMM * e * dist;
|
||||||
|
moveTo({x:x, y:y, e:emitMM}, speedMMM);
|
||||||
|
emitted += emitMM;
|
||||||
|
}
|
||||||
|
|
||||||
|
function drainQ() {
|
||||||
|
if (!arcDist) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (arcQ.length > 4) {
|
||||||
|
let area = BASE.newPolygon().addObj(arcQ).area();
|
||||||
|
let from = arcQ[0];
|
||||||
|
let to = arcQ.peek();
|
||||||
|
let cc = {x:0, y:0, z:0, r:0};
|
||||||
|
let cl = arcQ.length;
|
||||||
|
for (let center of arcQ.center) {
|
||||||
|
cc.x += center.x;
|
||||||
|
cc.y += center.y;
|
||||||
|
cc.z += center.z;
|
||||||
|
cc.r += center.r;
|
||||||
|
}
|
||||||
|
cc.x /= cl;
|
||||||
|
cc.y /= cl;
|
||||||
|
cc.z /= cl;
|
||||||
|
cc.r /= cl;
|
||||||
|
// first arc point
|
||||||
|
emitQrec(from);
|
||||||
|
// rest of arc to final point
|
||||||
|
let dist = arcQ.slice(1).map(v => v.dist).reduce((a,v) => a+v);
|
||||||
|
let emit = from.e;//arcQ.slice(1).map(v => v.e).reduce((a,v) => a+v);
|
||||||
|
emit = (from.emitPerMM * emit * dist);
|
||||||
|
outputLength += emit;
|
||||||
|
emitted += emit;
|
||||||
|
if (extrudeAbs) {
|
||||||
|
emit = outputLength;
|
||||||
|
}
|
||||||
|
let gc = area > 0 ? 'G2' : 'G3';
|
||||||
|
let pre = `${gc} X${to.x.toFixed(decimals)} Y${to.y.toFixed(decimals)} R${cc.r.toFixed(decimals)} E${emit.toFixed(decimals)}`;
|
||||||
|
let add = pos.f !== from.speedMMM ? ` E${from.speedMMM}` : '';
|
||||||
|
append(`${pre}${add} ; merged=${cl-1} dist=${dist.toFixed(decimals)}`);
|
||||||
|
pos.x = to.x;
|
||||||
|
pos.y = to.y;
|
||||||
|
pos.z = to.z;
|
||||||
|
} else {
|
||||||
|
for (let rec of arcQ) {
|
||||||
|
emitQrec(rec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arcQ.length = 0;
|
||||||
|
arcQ.center = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
if (inLoop) {
|
if (inLoop) {
|
||||||
append(`M808`);
|
append(`M808`);
|
||||||
|
|
|
||||||
|
|
@ -483,10 +483,12 @@ kiri.lang['en-us'] = {
|
||||||
ad_mins_l: "minimum speed\nfor short segments",
|
ad_mins_l: "minimum speed\nfor short segments",
|
||||||
ad_spol_s: "short path",
|
ad_spol_s: "short path",
|
||||||
ad_spol_l: "polygons shorter than this\nwill have their print speed\nscaled down to min speed\nin millimeters",
|
ad_spol_l: "polygons shorter than this\nwill have their print speed\nscaled down to min speed\nin millimeters",
|
||||||
|
ad_arct_s: "arc tolerance",
|
||||||
|
ad_arct_l: "convert faceted lines to arcs\ncenter point drift tolerance\nwhen matching arc points\nconsider values around 0.15\nin millimeters\n0 to disable",
|
||||||
ad_zhop_s: "z hop dist",
|
ad_zhop_s: "z hop dist",
|
||||||
ad_zhop_l: "amount to raise z\non retraction moves\nin millimeters\n0 to disable",
|
ad_zhop_l: "amount to raise z\non retraction moves\nin millimeters\n0 to disable",
|
||||||
ad_abkl_s: "anti-backlash",
|
ad_abkl_s: "anti-backlash",
|
||||||
ad_abkl_l: "use micro-movements to cancel\nbacklash during fills\nin millimeters",
|
ad_abkl_l: "for better flat surface finish\nuse micro-movements to cancel\nbacklash in solid layer output\nin millimeters\n0 to disable",
|
||||||
ad_lret_s: "layer retract",
|
ad_lret_s: "layer retract",
|
||||||
ad_lret_l: "force filament retraction\nbetween layers",
|
ad_lret_l: "force filament retraction\nbetween layers",
|
||||||
ad_play_s: "polish layers",
|
ad_play_s: "polish layers",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue