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
# Release 3.8
# Release 3.8 (2023-01-21)
* update server-side sample module code
* 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 refactor of contouring yields 2x - 20x speedup
* 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
- 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 custom gcode operator (can be used for pausing, too)
* 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 option to limit CAM trace ops to Z bottom limit (when in use)
* extend url loading of workspaces to all formats

View file

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

View file

@ -37,7 +37,7 @@ kiri.load(api => {
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 || {};
for (let [root, faces] of Object.entries(surfaces)) {
if (faces.contains(face)) {
@ -48,7 +48,7 @@ kiri.load(api => {
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) {
surfaces[face] = faces;
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);
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) {
@ -114,9 +114,9 @@ kiri.load(api => {
};
kiri.worker.cam_surface_find = function(data, send) {
const { id, face } = data;
const { id, face, radians } = data;
const widget = kiri.worker.cache[id];
const faces = CAM.surface_find(widget, [face]);
const faces = CAM.surface_find(widget, [face], radians);
send.done(faces);
}

View file

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

View file

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

View file

@ -10,7 +10,7 @@
gapp.register("kiri-mode.cam.slicer", [], (root, exports) => {
const { base, kiri } = root;
const { config, util, polygons, newOrderedLine, newPoint } = base;
const { config, util, polygons, newOrderedLine, newPoint, newLine } = base;
const { sliceConnect, sliceDedup } = base;
const { newSlice } = kiri;
@ -237,18 +237,27 @@ class Slicer {
}
async sliceBucketMinion(bucket, opt, oneach) {
const { decode, decodePointArray } = kiri.codec;
const slices = (await new Promise(resolve => {
kiri.minions.queue({
cmd: "cam_slice",
opt: { lines: false },
opt: Object.clone(opt),
bucket,
}, resolve);
})).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);
}
// console.log(bucket, slices);
return kiri.codec.decode(slices);
return slices;
}
async sliceBucket(bucket, opt, oneach) {
@ -472,10 +481,19 @@ moto.broker.subscribe("minion.started", msg => {
funcs.cam_slice = (data, seq) => {
const { bucket, opt } = data;
const { encode, encodePointArray } = kiri.codec;
// log({ slice: bucket, opt });
cache.slicer.sliceBucket(bucket, opt, slice => {
// console.log({ slice });
}).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,
boundsX,
boundsY,
minX,
minY,
zMin
});
@ -311,6 +313,10 @@ class Topo {
stepsTotal += ((maxX - minX + partOff * 2) / toolStep) | 0;
}
if (stepsTotal === 0) {
return;
}
const box = params.box.clone().expandByVector(new THREE.Vector3(
partOff, partOff, 0
));
@ -411,7 +417,7 @@ class Probe {
constructor(params) {
const { data, profile } = params;
const { stepsX, stepsY, boundsX, boundsY, zMin } = params;
const { stepsX, stepsY, boundsX, boundsY, zMin, minX, minY } = params;
this.params = params;

View file

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

View file

@ -527,6 +527,8 @@ self.kiri.lang['en-us'] = {
cp_xpnd_l: ["grow selected area to","encompass corners"],
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_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_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",