add lathe leave stock option, fix lathe progression between layers
This commit is contained in:
parent
52f0139114
commit
3e33e34598
6 changed files with 81 additions and 31 deletions
1
notes.md
1
notes.md
|
|
@ -68,6 +68,7 @@
|
|||
|
||||
# CAM
|
||||
|
||||
* `B` roughing leave stock should also increase Z slightly (sqrt(2) * leave)
|
||||
* `B` rapid moves should be max of terrain zmax and last cut layer height (roughing)
|
||||
* `B` in indexed stock mode, stock should rotate with indexing
|
||||
* `B` feed rate for next tool set before tool change (push/pop feed rates?)
|
||||
|
|
|
|||
|
|
@ -1348,6 +1348,8 @@ CAM.init = function(kiri, api) {
|
|||
angle: 'camLatheAngle',
|
||||
rate: 'camLatheSpeed',
|
||||
tolerance: 'camTolerance',
|
||||
filter: 'camContourFilter',
|
||||
leave: 'camContourLeave',
|
||||
axis: 'X'
|
||||
}).inputs = {
|
||||
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||
|
|
@ -1355,9 +1357,13 @@ CAM.init = function(kiri, api) {
|
|||
sep: UC.newBlank({class:"pop-sep"}),
|
||||
spindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:UC.toInt, show:hasSpindle}),
|
||||
rate: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:UC.toInt, units:true}),
|
||||
sep: UC.newBlank({class:"pop-sep"}),
|
||||
step: UC.newInput(LANG.cc_sovr_s, {title:LANG.cc_sovr_l, convert:UC.toFloat, bound:UC.bound(0.01,10.0)}),
|
||||
angle: UC.newInput(LANG.cc_sang_s, {title:LANG.cc_sang_l, convert:UC.toFloat, bound:UC.bound(0.01,90.0)}),
|
||||
sep: UC.newBlank({class:"pop-sep"}),
|
||||
tolerance: UC.newInput(LANG.ou_toll_s, {title:LANG.ou_toll_l, convert:UC.toFloat, bound:UC.bound(0,10.0), units:true, round:4}),
|
||||
leave: UC.newInput(LANG.cf_leav_s, {title:LANG.cf_leav_l, convert:UC.toFloat, bound:UC.bound(0,100)}),
|
||||
// filter: UC.newRow([ UC.newButton(LANG.filter, contourFilter) ], {class:"ext-buttons f-row"})
|
||||
};
|
||||
|
||||
createPopOp('trace', {
|
||||
|
|
|
|||
|
|
@ -255,13 +255,14 @@ CAM.export = function(print, online) {
|
|||
dx = opt.dx || newpos.x - pos.x,
|
||||
dy = opt.dy || newpos.y - pos.y,
|
||||
dz = opt.dz || newpos.z - pos.z,
|
||||
da = newpos.a != pos.a,
|
||||
maxf = dz ? maxZd : maxXYd,
|
||||
feed = Math.min(speed || maxf, maxf),
|
||||
dist = Math.sqrt(dx * dx + dy * dy + dz * dz),
|
||||
newFeed = feed && feed !== pos.f;
|
||||
|
||||
// drop dup points (all deltas are 0)
|
||||
if (!(dx || dy || dz)) {
|
||||
if (!(dx || dy || dz || da)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -285,7 +286,7 @@ CAM.export = function(print, online) {
|
|||
runbox.max.z = Math.max(runbox.max.z, pos.z);
|
||||
nl.append(space).append("Z").append(add0(pos.z * factor));
|
||||
}
|
||||
if (newpos.a !== pos.a) {
|
||||
if (da) {
|
||||
pos.a = newpos.a;
|
||||
nl.append(space).append("A").append(add0(pos.a * factor));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -749,6 +749,30 @@ class OpOutline extends CamOp {
|
|||
}
|
||||
}
|
||||
|
||||
function createFilter(op) {
|
||||
let filter = slices => slices;
|
||||
if (op.filter) {
|
||||
try {
|
||||
const obj = eval(`( ${op.filter.join('\n')} )`);
|
||||
let idx = 0;
|
||||
if (obj && obj.slices) {
|
||||
const nadd = [];
|
||||
filter = function(slices) {
|
||||
for (let slice of slices) {
|
||||
if (obj.slices(slice, idx++)) {
|
||||
nadd.push(slice);
|
||||
}
|
||||
}
|
||||
return nadd;
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('filter parse error', e, op.filter);
|
||||
}
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
|
||||
class OpContour extends CamOp {
|
||||
constructor(state, op) {
|
||||
super(state, op);
|
||||
|
|
@ -757,26 +781,7 @@ class OpContour extends CamOp {
|
|||
async slice(progress) {
|
||||
let { op, state } = this;
|
||||
let { addSlices } = state;
|
||||
let filter = slices => slices;
|
||||
if (op.filter) {
|
||||
try {
|
||||
const obj = eval(`( ${op.filter.join('\n')} )`);
|
||||
let idx = 0;
|
||||
if (obj && obj.slices) {
|
||||
const nadd = [];
|
||||
filter = function(slices) {
|
||||
for (let slice of slices) {
|
||||
if (obj.slices(slice, idx++)) {
|
||||
nadd.push(slice);
|
||||
}
|
||||
}
|
||||
return nadd;
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('filter parse error', e, op.filter);
|
||||
}
|
||||
}
|
||||
let filter = createFilter(op);
|
||||
// we need topo for safe travel moves when roughing and outlining
|
||||
// not generated when drilling-only. then all z moves use bounds max.
|
||||
// also generates x and y contouring when selected
|
||||
|
|
@ -869,6 +874,7 @@ class OpLathe extends CamOp {
|
|||
async slice(progress) {
|
||||
let { op, state } = this;
|
||||
let { addSlices } = state;
|
||||
let filter = createFilter(op);
|
||||
|
||||
this.topo = await CAM.Topo4({
|
||||
op,
|
||||
|
|
@ -877,6 +883,7 @@ class OpLathe extends CamOp {
|
|||
progress(pct, msg);
|
||||
},
|
||||
ondone: (slices) => {
|
||||
slices = filter(slices);
|
||||
this.slices = slices;
|
||||
addSlices(slices, false);
|
||||
}
|
||||
|
|
@ -893,6 +900,7 @@ class OpLathe extends CamOp {
|
|||
|
||||
let toolDiam = new CAM.Tool(settings, op.tool).fluteDiameter();
|
||||
let stepover = toolDiam * op.step * 2;
|
||||
let rez = topo.resolution;
|
||||
|
||||
setTool(op.tool, op.rate, op.plunge);
|
||||
setSpindle(op.spindle);
|
||||
|
|
@ -906,16 +914,42 @@ class OpLathe extends CamOp {
|
|||
continue;
|
||||
}
|
||||
|
||||
let last;
|
||||
for (let path of slice.camLines) {
|
||||
let latent;
|
||||
path.forEachPoint((point, pidx) => {
|
||||
camOut(point.clone(), pidx > 0, stepover);
|
||||
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, true, stepover);
|
||||
latent = undefined;
|
||||
}
|
||||
}
|
||||
camOut(last = point.clone(), pidx > 0, stepover);
|
||||
}, false);
|
||||
if (latent) {
|
||||
camOut(latent, true, stepover);
|
||||
}
|
||||
}
|
||||
|
||||
newLayer();
|
||||
}
|
||||
|
||||
setPrintPoint(printPoint);
|
||||
// move to safe height and reset A axis
|
||||
let last = ops.lastPoint();
|
||||
let amax = Math.round(last.a / 360) * 360;
|
||||
camOut(last = last.clone().setZ(zmax), 0);
|
||||
camOut(last = last.clone().setA(amax), 0);
|
||||
newLayer();
|
||||
ops.addGCode("G92A0");
|
||||
|
||||
setPrintPoint(last);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ function prepEach(widget, settings, print, firstPoint, update) {
|
|||
layerOut = [],
|
||||
printPoint,
|
||||
isNewMode,
|
||||
isLathe,
|
||||
tool,
|
||||
toolType,
|
||||
toolDiam,
|
||||
|
|
@ -327,7 +328,7 @@ function prepEach(widget, settings, print, firstPoint, update) {
|
|||
isMove = !cut;
|
||||
|
||||
// drop points too close together
|
||||
if (deltaXY < 0.001 && point.z === lastPoint.z) {
|
||||
if (!isLathe && deltaXY < 0.001 && point.z === lastPoint.z) {
|
||||
// console.trace(["drop dup",lastPoint,point]);
|
||||
return;
|
||||
}
|
||||
|
|
@ -346,7 +347,7 @@ function prepEach(widget, settings, print, firstPoint, update) {
|
|||
// new pos for plunge calc
|
||||
deltaXY = 0;
|
||||
}
|
||||
} else if (isMove && ['lathe'].contains(currentOp.type)) {
|
||||
} else if (isMove && isLathe) {
|
||||
if (point.z > lastPoint.z) {
|
||||
layerPush(lastPoint.clone().setZ(point.z), 0, 0, tool.getNumber());
|
||||
} else if (point.z < lastPoint.z) {
|
||||
|
|
@ -392,7 +393,7 @@ function prepEach(widget, settings, print, firstPoint, update) {
|
|||
}
|
||||
|
||||
// set new plunge rate
|
||||
if (!lasering && deltaZ < -tolerance && currentOp.type !== 'lathe') {
|
||||
if (!lasering && deltaZ < -tolerance && !isLathe) {
|
||||
let threshold = Math.min(deltaXY / 2, absDeltaZ),
|
||||
modifier = threshold / absDeltaZ;
|
||||
if (synthPlunge && threshold && modifier && deltaXY > tolerance) {
|
||||
|
|
@ -465,6 +466,7 @@ function prepEach(widget, settings, print, firstPoint, update) {
|
|||
setTolerance(0);
|
||||
nextIsMove = true;
|
||||
currentOp = op.op;
|
||||
isLathe = currentOp.type === 'lathe';
|
||||
let weight = op.weight();
|
||||
newLayer(op.op);
|
||||
op.prepare(ops, (progress, message) => {
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ class Topo4 {
|
|||
this.maxo = tool.profileDim.maxo * resolution;
|
||||
this.diam = tool.fluteDiameter();
|
||||
this.zoff = widget.track.top || 0;
|
||||
this.leave = op.leave || 0;
|
||||
|
||||
onupdate(0, "lathe");
|
||||
|
||||
|
|
@ -90,6 +91,8 @@ class Topo4 {
|
|||
onupdate(1, "lathe");
|
||||
ondone(lathe);
|
||||
// ondone([...slices, ...lathe]);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
async slice(onupdate) {
|
||||
|
|
@ -300,7 +303,7 @@ class Topo4 {
|
|||
}
|
||||
|
||||
async latheWorker(onupdate) {
|
||||
const { sliced, tool, zoff } = this;
|
||||
const { sliced, tool, zoff, leave } = this;
|
||||
|
||||
const rota = this.angle * DEG2RAD;
|
||||
const steps = (Math.PI * 2) / rota;
|
||||
|
|
@ -335,7 +338,8 @@ class Topo4 {
|
|||
for (let rec of recs) {
|
||||
const { degrees, heights } = rec;
|
||||
[...heights].group(3).forEach((a,i) => {
|
||||
paths[i].camLines[0].push( newPoint(a[0], a[1], a[2]).setA(degrees) );
|
||||
// progress each path 360 degrees to prevent A rolling backwards
|
||||
paths[i].camLines[0].push( newPoint(a[0], a[1], a[2] + leave).setA(degrees+ i * -360) );
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -345,7 +349,9 @@ class Topo4 {
|
|||
console.log('empty', slice);
|
||||
continue;
|
||||
}
|
||||
slice.camLines[0].push(poly.points[0].clone());
|
||||
// repeat first point 360 degrees progressed
|
||||
const repeat = poly.points[0];
|
||||
slice.camLines[0].push(repeat.clone().setA(repeat.a - 360));
|
||||
slice.output()
|
||||
.setLayer("lathe", { line: 0xffff00 })
|
||||
.addPoly(poly.clone().applyRotations().move({ z: -zoff, x:0, y:0 }));
|
||||
|
|
@ -407,7 +413,7 @@ function rotatePoints(lines, rot) {
|
|||
new THREE.BufferAttribute(lines, 3).applyMatrix4(rot);
|
||||
}
|
||||
|
||||
CAM.Topo4 = async function(opt) {
|
||||
CAM.Topo4 = function(opt) {
|
||||
return new Topo4().generate(opt);
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue