complete threading support for all slicing ops. add pocket surface selection criteria

This commit is contained in:
Stewart Allen 2023-01-15 16:36:05 -05:00
commit fa6d07ed15
9 changed files with 62 additions and 27 deletions

View file

@ -3,7 +3,7 @@
Full docs @ https://docs.grid.space/projects/kiri-moto Full docs @ https://docs.grid.space/projects/kiri-moto
# Release 3.8 # Release 3.8 (2023-01-21)
* update server-side sample module code * update server-side sample module code
* various fixes and improvements to CAM indexing * various fixes and improvements to CAM indexing
@ -23,6 +23,7 @@ Full docs @ https://docs.grid.space/projects/kiri-moto
* CAM fix tracing nested polyline offset ordering * CAM fix tracing nested polyline offset ordering
* CAM refactor of contouring yields 2x - 20x speedup * CAM refactor of contouring yields 2x - 20x speedup
* CAM update traces to async slicing, fix use with flip * CAM update traces to async slicing, fix use with flip
* CAM add threading support for all slicing ops
- refactor object/group storage model in Mesh:Tool - refactor object/group storage model in Mesh:Tool
- add omit pocket to rough and outline - add omit pocket to rough and outline
@ -85,6 +86,7 @@ Full docs @ https://docs.grid.space/projects/kiri-moto
* add CAM Z bottom inversion option to flip operator * add CAM Z bottom inversion option to flip operator
* add CAM custom gcode operator (can be used for pausing, too) * add CAM custom gcode operator (can be used for pausing, too)
* add CAM z extend option on registration op independent of "Z Thru" global * add CAM z extend option on registration op independent of "Z Thru" global
* add CAM pocket surface selection filter by angle
* add optional CAM operation notes (helps with many similar ops) * add optional CAM operation notes (helps with many similar ops)
* add option to limit CAM trace ops to Z bottom limit (when in use) * add option to limit CAM trace ops to Z bottom limit (when in use)
* extend url loading of workspaces to all formats * extend url loading of workspaces to all formats

View file

@ -844,6 +844,7 @@ CAM.init = function(kiri, api) {
func.clearPops(); func.clearPops();
alert = api.show.alert("analyzing surfaces...", 1000); alert = api.show.alert("analyzing surfaces...", 1000);
let surfaces = poppedRec.surfaces; let surfaces = poppedRec.surfaces;
let radians = poppedRec.follow * DEG2RAD;
CAM.surface_prep(currentIndex * RAD2DEG, () => { CAM.surface_prep(currentIndex * RAD2DEG, () => {
api.hide.alert(alert); api.hide.alert(alert);
alert = api.show.alert("[esc] cancels surface editing"); alert = api.show.alert("[esc] cancels surface editing");
@ -851,7 +852,7 @@ CAM.init = function(kiri, api) {
let widget = api.widgets.forid(wid); let widget = api.widgets.forid(wid);
if (widget && arr.length) if (widget && arr.length)
for (let faceid of arr) { for (let faceid of arr) {
CAM.surface_toggle(widget, faceid, faceids => { CAM.surface_toggle(widget, faceid, radians, faceids => {
// surfaces[widget.id] = faceids; // surfaces[widget.id] = faceids;
}); });
} }
@ -864,7 +865,7 @@ CAM.init = function(kiri, api) {
let min = Math.min(face.a, face.b, face.c); let min = Math.min(face.a, face.b, face.c);
let faceid = min / 3; let faceid = min / 3;
let widget = lastWidget = obj.object.widget; let widget = lastWidget = obj.object.widget;
CAM.surface_toggle(widget, faceid, faceids => { CAM.surface_toggle(widget, faceid, radians, faceids => {
surfaces[widget.id] = faceids; surfaces[widget.id] = faceids;
}); });
}; };
@ -1338,10 +1339,11 @@ CAM.init = function(kiri, api) {
plunge: 'camPocketPlunge', plunge: 'camPocketPlunge',
expand: 'camPocketExpand', expand: 'camPocketExpand',
smooth: 'camPocketSmooth', smooth: 'camPocketSmooth',
refine: 'cmaPocketRefine', refine: 'camPocketRefine',
follow: 'camPocketFollow',
contour: 'camPocketContour', contour: 'camPocketContour',
engrave: 'camPocketEngrave', engrave: 'camPocketEngrave',
outline: 'cmaPocketOutline', outline: 'camPocketOutline',
tolerance: 'camTolerance', tolerance: 'camTolerance',
}).inputs = { }).inputs = {
tool: UC.newSelect(LANG.cc_tool, {}, "tools"), tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
@ -1354,8 +1356,9 @@ CAM.init = function(kiri, api) {
sep: UC.newBlank({class:"pop-sep"}), sep: UC.newBlank({class:"pop-sep"}),
expand: UC.newInput(LANG.cp_xpnd_s, {title:LANG.cp_xpnd_l, convert:UC.toFloat, units:true, show:() => !poppedRec.contour}), expand: UC.newInput(LANG.cp_xpnd_s, {title:LANG.cp_xpnd_l, convert:UC.toFloat, units:true, show:() => !poppedRec.contour}),
refine: UC.newInput(LANG.cp_refi_s, {title:LANG.cp_refi_l, convert:UC.toInt, show:() => poppedRec.contour}), refine: UC.newInput(LANG.cp_refi_s, {title:LANG.cp_refi_l, convert:UC.toInt, show:() => poppedRec.contour}),
smooth: UC.newInput(LANG.cp_smoo_s, {title:LANG.cp_smoo_l, convert:UC.toFloat, units:true}), smooth: UC.newInput(LANG.cp_smoo_s, {title:LANG.cp_smoo_l, convert:UC.toInt}),
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, show:() => poppedRec.contour}), 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, show:() => poppedRec.contour}),
follow: UC.newInput(LANG.cp_foll_s, {title:LANG.cp_foll_l, convert:UC.toFloat}),
sep: UC.newBlank({class:"pop-sep"}), sep: UC.newBlank({class:"pop-sep"}),
contour: UC.newBoolean(LANG.cp_cont_s, undefined, {title:LANG.cp_cont_s}), contour: UC.newBoolean(LANG.cp_cont_s, undefined, {title:LANG.cp_cont_s}),
outline: UC.newBoolean(LANG.cp_outl_s, undefined, {title:LANG.cp_outl_l, show:() => !poppedRec.contour}), outline: UC.newBoolean(LANG.cp_outl_s, undefined, {title:LANG.cp_outl_l, show:() => !poppedRec.contour}),

View file

@ -37,7 +37,7 @@ kiri.load(api => {
widget.selectFaces(Object.values(widget._surfaces).flat()); widget.selectFaces(Object.values(widget._surfaces).flat());
}; };
CAM.surface_toggle = function(widget, face, ondone) { CAM.surface_toggle = function(widget, face, radians, ondone) {
let surfaces = widget._surfaces = widget._surfaces || {}; let surfaces = widget._surfaces = widget._surfaces || {};
for (let [root, faces] of Object.entries(surfaces)) { for (let [root, faces] of Object.entries(surfaces)) {
if (faces.contains(face)) { if (faces.contains(face)) {
@ -48,7 +48,7 @@ kiri.load(api => {
return; return;
} }
} }
kiri.client.send("cam_surface_find", { id: widget.id, face }, faces => { kiri.client.send("cam_surface_find", { id: widget.id, face, radians }, faces => {
if (faces.length) { if (faces.length) {
surfaces[face] = faces; surfaces[face] = faces;
CAM.surface_show(widget); CAM.surface_show(widget);
@ -92,9 +92,9 @@ kiri.load(api => {
} }
}; };
CAM.surface_find = function(widget, faces) { CAM.surface_find = function(widget, faces, radians) {
CAM.surface_prep(widget); CAM.surface_prep(widget);
return widget.tool.findConnectedSurface(faces, 0.1, 0.0); return widget.tool.findConnectedSurface(faces, radians || 0, 0.0);
}; };
kiri.worker.cam_surfaces = function(data, send) { kiri.worker.cam_surfaces = function(data, send) {
@ -114,9 +114,9 @@ kiri.load(api => {
}; };
kiri.worker.cam_surface_find = function(data, send) { kiri.worker.cam_surface_find = function(data, send) {
const { id, face } = data; const { id, face, radians } = data;
const widget = kiri.worker.cache[id]; const widget = kiri.worker.cache[id];
const faces = CAM.surface_find(widget, [face]); const faces = CAM.surface_find(widget, [face], radians);
send.done(faces); send.done(faces);
} }

View file

@ -1054,7 +1054,9 @@ class OpPocket extends CamOp {
onupdate: (index, total, msg) => { onupdate: (index, total, msg) => {
progress((index / total) * 0.9, msg); progress((index / total) * 0.9, msg);
}, },
ondone: (slices) => { }, ondone: (slices) => {
// console.log({ contour: slices });
},
contour: { contour: {
tool, tool,
tolerance, tolerance,

View file

@ -333,13 +333,13 @@ CAM.traces = async function(settings, widget, single) {
let slicer = new kiri.cam_slicer(widget); let slicer = new kiri.cam_slicer(widget);
let indices = [...new Set(Object.keys(slicer.zFlat) let indices = [...new Set(Object.keys(slicer.zFlat)
.map(kv => parseFloat(kv).round(5)) .map(kv => parseFloat(kv).round(5))
.appendAll(Object.entries(slicer.zLine).map(ze => { // .appendAll(Object.entries(slicer.zLine).map(ze => {
let [ zk, zv ] = ze; // let [ zk, zv ] = ze;
return zv > 1 ? parseFloat(zk).round(5) : null; // return zv > 1 ? parseFloat(zk).round(5) : null;
}) // })
.filter(v => v !== null)))] // .filter(v => v !== null))
)]
.sort((a,b) => b - a); .sort((a,b) => b - a);
let traces = []; let traces = [];
// find and trim polys (including open) to shadow // find and trim polys (including open) to shadow
let oneach = data => { let oneach = data => {
@ -369,8 +369,9 @@ CAM.traces = async function(settings, widget, single) {
traces.push(poly); traces.push(poly);
}); });
}; };
let opts = { each: oneach, over: false, flatoff: 0, edges: true, openok: true }; let opts = { each: oneach, over: false, flatoff: 0, edges: true, openok: true, lines: true };
await slicer.slice(indices, opts); await slicer.slice(indices, opts);
// pick up bottom features
opts.over = true; opts.over = true;
await slicer.slice(indices, opts); await slicer.slice(indices, opts);
widget.traces = traces; widget.traces = traces;

View file

@ -10,7 +10,7 @@
gapp.register("kiri-mode.cam.slicer", [], (root, exports) => { gapp.register("kiri-mode.cam.slicer", [], (root, exports) => {
const { base, kiri } = root; const { base, kiri } = root;
const { config, util, polygons, newOrderedLine, newPoint } = base; const { config, util, polygons, newOrderedLine, newPoint, newLine } = base;
const { sliceConnect, sliceDedup } = base; const { sliceConnect, sliceDedup } = base;
const { newSlice } = kiri; const { newSlice } = kiri;
@ -237,18 +237,27 @@ class Slicer {
} }
async sliceBucketMinion(bucket, opt, oneach) { async sliceBucketMinion(bucket, opt, oneach) {
const { decode, decodePointArray } = kiri.codec;
const slices = (await new Promise(resolve => { const slices = (await new Promise(resolve => {
kiri.minions.queue({ kiri.minions.queue({
cmd: "cam_slice", cmd: "cam_slice",
opt: { lines: false }, opt: Object.clone(opt),
bucket, bucket,
}, resolve); }, resolve);
})).slices; })).slices;
for (let slice of slices) { for (let slice of slices) {
slice.polys = decode(slice.polys);
if (slice.lines) {
slice.lines = decodePointArray(slice.lines)
.group(2)
.map(arr => {
return newLine(arr[0], arr[1])
});
}
oneach(slice); oneach(slice);
} }
// console.log(bucket, slices); // console.log(bucket, slices);
return kiri.codec.decode(slices); return slices;
} }
async sliceBucket(bucket, opt, oneach) { async sliceBucket(bucket, opt, oneach) {
@ -472,10 +481,19 @@ moto.broker.subscribe("minion.started", msg => {
funcs.cam_slice = (data, seq) => { funcs.cam_slice = (data, seq) => {
const { bucket, opt } = data; const { bucket, opt } = data;
const { encode, encodePointArray } = kiri.codec;
// log({ slice: bucket, opt });
cache.slicer.sliceBucket(bucket, opt, slice => { cache.slicer.sliceBucket(bucket, opt, slice => {
// console.log({ slice }); // console.log({ slice });
}).then(data => { }).then(data => {
reply({ seq, slices: kiri.codec.encode(data) }); data.forEach(rec => {
rec.polys = encode(rec.polys);
if (rec.lines) {
const points = rec.lines.map(l => [l.p1, l.p2]).flat();
rec.lines = encodePointArray(points);
}
});
reply({ seq, slices: data });
}); });
}; };
}); });

View file

@ -119,6 +119,8 @@ class Topo {
stepsY, stepsY,
boundsX, boundsX,
boundsY, boundsY,
minX,
minY,
zMin zMin
}); });
@ -311,6 +313,10 @@ class Topo {
stepsTotal += ((maxX - minX + partOff * 2) / toolStep) | 0; stepsTotal += ((maxX - minX + partOff * 2) / toolStep) | 0;
} }
if (stepsTotal === 0) {
return;
}
const box = params.box.clone().expandByVector(new THREE.Vector3( const box = params.box.clone().expandByVector(new THREE.Vector3(
partOff, partOff, 0 partOff, partOff, 0
)); ));
@ -411,7 +417,7 @@ class Probe {
constructor(params) { constructor(params) {
const { data, profile } = params; const { data, profile } = params;
const { stepsX, stepsY, boundsX, boundsY, zMin } = params; const { stepsX, stepsY, boundsX, boundsY, zMin, minX, minY } = params;
this.params = params; this.params = params;

View file

@ -514,10 +514,11 @@ const conf = exports({
camPocketPlunge: 200, camPocketPlunge: 200,
camPocketExpand: 0, camPocketExpand: 0,
camPocketSmooth: 0, camPocketSmooth: 0,
cmaPocketRefine: 20, camPocketRefine: 20,
camPocketFollow: 5,
camPocketContour: false, camPocketContour: false,
camPocketEngrave: false, camPocketEngrave: false,
cmaPocketOutline: false, camPocketOutline: false,
camDrillTool: 1000, camDrillTool: 1000,
camDrillSpindle: 1000, camDrillSpindle: 1000,
camDrillDownSpeed: 250, camDrillDownSpeed: 250,

View file

@ -527,6 +527,8 @@ self.kiri.lang['en-us'] = {
cp_xpnd_l: ["grow selected area to","encompass corners"], cp_xpnd_l: ["grow selected area to","encompass corners"],
cp_smoo_s: "smooth", cp_smoo_s: "smooth",
cp_smoo_l: ["clean up jagged edges caused by angled walls. can speedup and improve pocketing for detailed geometries. recommend starting with values around 1 if slicing takes too long or the contours look jagged"], cp_smoo_l: ["clean up jagged edges caused by angled walls. can speedup and improve pocketing for detailed geometries. recommend starting with values around 1 if slicing takes too long or the contours look jagged"],
cp_foll_s: "selection",
cp_foll_l: ["curvature selection limit in degrees. values closer to 0 will restrict selections to flatter surfaces"],
cp_refi_s: "refine", cp_refi_s: "refine",
cp_refi_l: ["number of refining passes to perform on contoured polylines. meant to address Z delta sawtoothing caused by faced geometries whereas smoothing handles XY. values > 10 work well for gently contoured geometries with significant Z movement."], cp_refi_l: ["number of refining passes to perform on contoured polylines. meant to address Z delta sawtoothing caused by faced geometries whereas smoothing handles XY. values > 10 work well for gently contoured geometries with significant Z movement."],
cp_cont_s: "contour", cp_cont_s: "contour",