get first version of the arc que operational
This commit is contained in:
parent
234ce115be
commit
bdf131109c
1 changed files with 186 additions and 116 deletions
|
|
@ -11,7 +11,7 @@
|
|||
gapp.register("kiri-mode.cam.prepare", (root, exports) => {
|
||||
|
||||
const { base, kiri } = root;
|
||||
const { paths, polygons, newPoint } = base;
|
||||
const { paths, polygons, newPoint, util} = base;
|
||||
const { tip2tipEmit, poly2polyEmit } = paths;
|
||||
const { driver, render } = kiri;
|
||||
const { CAM } = driver;
|
||||
|
|
@ -312,7 +312,7 @@ function prepEach(widget, settings, print, firstPoint, update) {
|
|||
/**
|
||||
* emit a cut or move operation from the current location to a new location
|
||||
* @param {Point} point destination for move
|
||||
* @param {1|2} cut 1/true = cut, 0/false = move
|
||||
* @param {1|0|boolean} cut 1/true = cut, 0/false = move
|
||||
* @param {number} opts.radius arc radius; truthy values for arc move
|
||||
* @param {boolean} opts.clockwise arc direction
|
||||
* @param {number} opts.moveLen typically = tool diameter used to trigger terrain detection
|
||||
|
|
@ -699,115 +699,182 @@ function prepEach(widget, settings, print, firstPoint, update) {
|
|||
*/
|
||||
function polyEmit(poly, index, count, fromPoint) {
|
||||
|
||||
console.log('polyEmit', poly, index, count);
|
||||
const arcDist = 1,
|
||||
arcRes = 2, //2 degs max
|
||||
arcMax = Infinity; // no max arc radius
|
||||
|
||||
// if (fromPoint && out.emit) {
|
||||
// if (arcDist) {
|
||||
// let rec = {e:out.emit, x, y, z, dist, emitPerMM, speedMMM};
|
||||
// arcQ.push(rec);
|
||||
// let deem = false; // do arcQ[0] and rec have differing emit values?
|
||||
// let depm = false; // do arcQ[0] and rec have differing emit speeds?
|
||||
// let desp = false; // do arcQ[0] and rec have differing move speeds?
|
||||
// if (arcQ.length > 1) {
|
||||
// let el = arcQ.length;
|
||||
// deem = arcQ[0].e !== rec.e;
|
||||
// depm = arcQ[0].emitPerMM !== rec.emitPerMM;
|
||||
// desp = arcQ[0].speedMMM !== rec.speedMMM;
|
||||
// }
|
||||
// // ondebug({arcQ});
|
||||
// if (arcQ.length > 2) {
|
||||
// let el = arcQ.length;
|
||||
// let e1 = arcQ[0]; // first in arcQ
|
||||
// let e2 = arcQ[Math.floor(el/2)]; // mid in arcQ
|
||||
// let e3 = arcQ[el-1]; // last in arcQ
|
||||
// let e4 = arcQ[el-2]; // second last in arcQ
|
||||
// let e5 = arcQ[el-3]; // third last in arcQ
|
||||
// let cc = util.center2d(e1, e2, e3, 1); // find center
|
||||
// let lr = util.center2d(e3, e4, e5, 1); // find local radius
|
||||
// let dc = 0;
|
||||
// console.log('polyEmit', poly, index, count);
|
||||
|
||||
// let radFault = false;
|
||||
// if (lr) {
|
||||
// let angle = 2 * Math.asin(dist/(2*lr.r));
|
||||
// radFault = Math.abs(angle) > Math.PI * 2 / arcRes; // enforce arcRes(olution)
|
||||
// // if (arcQ.center) {
|
||||
// // arcQ.rSum = arcQ.center.reduce( function (t, v) { return t + v.r }, 0 );
|
||||
// // let avg = arcQ.rSum / arcQ.center.length;
|
||||
// // radFault = radFault || Math.abs(avg - lr.r) / avg > arcDev; // eliminate sharps and flats when local rad is out of arcDev(iation)
|
||||
// // }
|
||||
// } else {
|
||||
// radFault = true;
|
||||
// }
|
||||
let arcQ = [];
|
||||
|
||||
// if (cc) {
|
||||
// if ([cc.x,cc.y,cc.z,cc.r].hasNaN()) {
|
||||
// console.log({cc, e1, e2, e3});
|
||||
// }
|
||||
// if (arcQ.length === 3) {
|
||||
// arcQ.center = [ cc ];
|
||||
// arcQ.xSum = cc.x;
|
||||
// arcQ.ySum = cc.y;
|
||||
// arcQ.rSum = cc.r;
|
||||
// } else {
|
||||
// // check center point delta
|
||||
// arcQ.xSum = arcQ.center.reduce( function (t, v) { return t + v.x }, 0 );
|
||||
// arcQ.ySum = arcQ.center.reduce( function (t, v) { return t + v.y }, 0 );
|
||||
// arcQ.rSum = arcQ.center.reduce( function (t, v) { return t + v.r }, 0 );
|
||||
// let dx = cc.x - arcQ.xSum / arcQ.center.length;
|
||||
// let dy = cc.y - arcQ.ySum / arcQ.center.length;
|
||||
// dc = Math.sqrt(dx * dx + dy * dy);
|
||||
// }
|
||||
function arcExport(point,lastp){
|
||||
|
||||
// // if new point is off the arc
|
||||
// // if (deem || depm || desp || dc > arcDist || cc.r < arcMin || cc.r > arcMax || dist > cc.r) {
|
||||
// if (deem || depm || desp || dc * arcQ.center.length / arcQ.rSum > arcDist || dist > cc.r || cc.r > arcMax || radFault || !arcValid()) {
|
||||
// // let debug = [deem, depm, desp, dc * arcQ.center.length / arcQ.rSum > arcDist, dist > cc.r, cc.r > arcMax, radFault];
|
||||
// if (arcQ.length === 4) {
|
||||
// // not enough points for an arc, drop first point and recalc center
|
||||
// emitQrec(arcQ.shift());
|
||||
// let tc = util.center2d(arcQ[0], arcQ[1], arcQ[2], 1);
|
||||
// // the new center is invalid as well. drop the first point
|
||||
// if (!tc) {
|
||||
// emitQrec(arcQ.shift());
|
||||
// } else {
|
||||
// arcQ.center = [ tc ];
|
||||
// let angle = 2 * Math.asin(arcQ[1].dist/(2*tc.r));
|
||||
// if (Math.abs(angle) > Math.PI * 2 / arcRes) { // enforce arcRes on initial angle
|
||||
// emitQrec(arcQ.shift());
|
||||
// }
|
||||
// }
|
||||
// } 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 {
|
||||
// // drainQ on invalid center
|
||||
// drainQ();
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// // emitMM = emitPerMM * out.emit * dist;
|
||||
// emitMM = extrudeMM(dist, emitPerMM, out.emit);
|
||||
// moveTo({x:x, y:y, e:emitMM}, speedMMM);
|
||||
// emitted += emitMM;
|
||||
// }
|
||||
// } else {
|
||||
// drainQ();
|
||||
// moveTo({x:x, y:y}, seekMMM);
|
||||
// // TODO disabling out of plane z moves until a better mechanism
|
||||
// // can be built that doesn't rely on computed zpos from layer heights...
|
||||
// // when making z moves (like polishing) allow slowdown vs fast seek
|
||||
// // let moveSpeed = (lastp && lastp.z !== z) ? speedMMM : seekMMM;
|
||||
// // moveTo({x:x, y:y, z:z}, moveSpeed);
|
||||
// }
|
||||
let dist = lastp? point.distTo2D(lastp) : 0;
|
||||
|
||||
if (lastp) {
|
||||
if (arcDist) {
|
||||
let rec = Object.assign(point,{dist});
|
||||
arcQ.push(rec);
|
||||
let desp = false; // do arcQ[0] and rec have differing move speeds?
|
||||
if (arcQ.length > 1) {
|
||||
let el = arcQ.length;
|
||||
desp = arcQ[0].speedMMM !== rec.speedMMM;
|
||||
}
|
||||
// ondebug({arcQ});
|
||||
if (arcQ.length > 2) {
|
||||
let el = arcQ.length;
|
||||
let e1 = arcQ[0]; // first in arcQ
|
||||
let e2 = arcQ[Math.floor(el/2)]; // mid in arcQ
|
||||
let e3 = arcQ[el-1]; // last in arcQ
|
||||
let e4 = arcQ[el-2]; // second last in arcQ
|
||||
let e5 = arcQ[el-3]; // third last in arcQ
|
||||
let cc = util.center2d(e1, e2, e3, 1); // find center
|
||||
let lr = util.center2d(e3, e4, e5, 1); // find local radius
|
||||
let dc = 0;
|
||||
|
||||
let radFault = false;
|
||||
if (lr) {
|
||||
let angle = 2 * Math.asin(dist/(2*lr.r));
|
||||
radFault = Math.abs(angle) > Math.PI * 2 / arcRes; // enforce arcRes(olution)
|
||||
// if (arcQ.center) {
|
||||
// arcQ.rSum = arcQ.center.reduce( function (t, v) { return t + v.r }, 0 );
|
||||
// let avg = arcQ.rSum / arcQ.center.length;
|
||||
// radFault = radFault || Math.abs(avg - lr.r) / avg > arcDev; // eliminate sharps and flats when local rad is out of arcDev(iation)
|
||||
// }
|
||||
} else {
|
||||
radFault = true;
|
||||
}
|
||||
|
||||
if (cc) {
|
||||
if ([cc.x,cc.y,cc.z,cc.r].hasNaN()) {
|
||||
console.log({cc, e1, e2, e3});
|
||||
}
|
||||
if (arcQ.length === 3) {
|
||||
arcQ.center = [ cc ];
|
||||
arcQ.xSum = cc.x;
|
||||
arcQ.ySum = cc.y;
|
||||
arcQ.rSum = cc.r;
|
||||
} else {
|
||||
// check center point delta
|
||||
arcQ.xSum = arcQ.center.reduce( function (t, v) { return t + v.x }, 0 );
|
||||
arcQ.ySum = arcQ.center.reduce( function (t, v) { return t + v.y }, 0 );
|
||||
arcQ.rSum = arcQ.center.reduce( function (t, v) { return t + v.r }, 0 );
|
||||
let dx = cc.x - arcQ.xSum / arcQ.center.length;
|
||||
let dy = cc.y - arcQ.ySum / arcQ.center.length;
|
||||
dc = Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
// if new point is off the arc
|
||||
// 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 ) {
|
||||
// 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));
|
||||
if (arcQ.length === 4) {
|
||||
// not enough points for an arc, drop first point and recalc center
|
||||
camOut(arcQ.shift(),1);
|
||||
let tc = util.center2d(arcQ[0], arcQ[1], arcQ[2], 1);
|
||||
// the new center is invalid as well. drop the first point
|
||||
if (!tc) {
|
||||
camOut(arcQ.shift(),1);
|
||||
} else {
|
||||
arcQ.center = [ tc ];
|
||||
let angle = 2 * Math.asin(arcQ[1].dist/(2*tc.r));
|
||||
if (Math.abs(angle) > Math.PI * 2 / arcRes) { // enforce arcRes on initial angle
|
||||
camOut(arcQ.shift(),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 {
|
||||
// drainQ on invalid center
|
||||
drainQ();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// emitMM = emitPerMM * out.emit * dist;
|
||||
emitMM = extrudeMM(dist, emitPerMM, out.emit);
|
||||
camOut({x, y, e:emitMM}, true,);
|
||||
emitted += emitMM;
|
||||
}
|
||||
} else {
|
||||
// if no last point, emit and set
|
||||
drainQ();
|
||||
camOut({x, y},1 );
|
||||
// TODO disabling out of plane z moves until a better mechanism
|
||||
// can be built that doesn't rely on computed zpos from layer heights...
|
||||
// when making z moves (like polishing) allow slowdown vs fast seek
|
||||
// let moveSpeed = (lastp && lastp.z !== z) ? speedMMM : seekMMM;
|
||||
// moveTo({x:x, y:y, z:z}, moveSpeed);
|
||||
}
|
||||
return point;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function drainQ() {
|
||||
|
||||
console.log("drainQ called",structuredClone(arcQ));
|
||||
|
||||
if (!arcDist) {
|
||||
return;
|
||||
}
|
||||
if (arcQ.length > 4) {
|
||||
// ondebug({arcQ});
|
||||
let vec1 = new THREE.Vector2(arcQ[1].x - arcQ[0].x, arcQ[1].y - arcQ[0].y);
|
||||
let vec2 = new THREE.Vector2(arcQ.center[0].x - arcQ[0].x, arcQ.center[0].y - arcQ[0].y);
|
||||
let clockwise = vec1.cross(vec2) < 0 ? 'G2' : 'G3';
|
||||
let from = arcQ[0];
|
||||
let to = arcQ.peek();
|
||||
arcQ.xSum = arcQ.center.reduce( (t, v) => t + v.x , 0 );
|
||||
arcQ.ySum = arcQ.center.reduce( (t, v) => t + v.y , 0 );
|
||||
arcQ.rSum = arcQ.center.reduce( (t, v) => t + v.r , 0 );
|
||||
let cl = arcQ.center.length;
|
||||
let cc;
|
||||
|
||||
let angle = util.thetaDiff(
|
||||
Math.atan2((from.y - arcQ.ySum / cl), (from.x - arcQ.xSum / cl)),
|
||||
Math.atan2((to.y - arcQ.ySum / cl), (to.x - arcQ.xSum / cl)),
|
||||
clockwise
|
||||
);
|
||||
|
||||
if (Math.abs(angle) <= 3 * Math.PI / 4) {
|
||||
cc = util.center2pr(from, to, arcQ.rSum / cl, !clockwise);
|
||||
}
|
||||
|
||||
if (!cc) {
|
||||
cc = {x:arcQ.xSum/cl, y:arcQ.ySum/cl, z:arcQ[0].z, r:arcQ.rSum/cl};
|
||||
}
|
||||
|
||||
// first arc point
|
||||
camOut(from,true);
|
||||
// rest of arc to final point
|
||||
|
||||
// XYR form
|
||||
// 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});
|
||||
// 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 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)}`);
|
||||
} else {
|
||||
//if q too short, emit as lines
|
||||
for (let rec of arcQ) {
|
||||
camOut(rec,1);
|
||||
}
|
||||
}
|
||||
arcQ.length = 0;
|
||||
arcQ.center = undefined;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -815,19 +882,22 @@ function prepEach(widget, settings, print, firstPoint, update) {
|
|||
// scale speed of first cutting poly since it engages the full bit
|
||||
let scale = ((isRough || isPocket) && count === 1) ? engageFactor : 1;
|
||||
|
||||
if (easeDown && poly.isClosed()) {
|
||||
last = generateEaseDown((point, pidx, points, offset)=>{
|
||||
|
||||
camOut(point.clone(), 1, {factor:scale});
|
||||
if (easeDown && poly.isClosed()) { //if doing ease-down
|
||||
last = generateEaseDown((point, )=>{ //generate ease-down points
|
||||
camOut(point.clone(), 1, {factor:scale}); // and pass them to camOut
|
||||
}, poly, fromPoint, easeAngle);
|
||||
}
|
||||
console.log(last,last)
|
||||
|
||||
poly.forEachPoint(function(point, pidx, points, offset) {
|
||||
arcExport(point,last)
|
||||
// camOut(point.clone(), offset !== 0, {factor:scale});
|
||||
last = point;
|
||||
camOut(point.clone(), offset !== 0, {factor:scale});
|
||||
}, poly.isClosed(), last);
|
||||
|
||||
// console.log("at end of arcExport",structuredClone(arcQ));
|
||||
drainQ();
|
||||
// console.log("at end of arcExport",structuredClone(arcQ));
|
||||
|
||||
|
||||
newLayer();
|
||||
return last;
|
||||
|
|
|
|||
Loading…
Reference in a new issue