when healing enabled, warn when non-manifold geometry detected. update release notes
This commit is contained in:
parent
0f756c074b
commit
059dbced58
8 changed files with 62 additions and 14 deletions
1
notes.md
1
notes.md
|
|
@ -79,6 +79,7 @@
|
|||
* `F` add option for op-major ordering (instead of part major)
|
||||
* `F` animate only selected range (as an option)
|
||||
* `F` add `plunge max` to contouring that can override z feed limit
|
||||
* `F` add ability to select regions for contouring op (like pocketing)
|
||||
* `F` roughing flats should be constrained to flat region, not create a layer
|
||||
* `F` limit cut depth to flute length of selected tool (or warn)
|
||||
* `F` change color of line selection in trace op when not a closed poly
|
||||
|
|
|
|||
10
release.md
10
release.md
|
|
@ -7,6 +7,16 @@ Full docs @ https://docs.grid.space/projects/kiri-moto
|
|||
|
||||
## Kiri:moto
|
||||
|
||||
* add support to run as Progressive Web Apps for installation and offline use
|
||||
* add assembly import when KM used inside of Onshape
|
||||
* add configurable flatness for contour clipping
|
||||
* add axis label remapping in FDM
|
||||
* extend url loading of workspaces to all formats
|
||||
* alert when healing is enabled and non-manifold geometries are detected
|
||||
* fix thin output start and end point tracking which broke retraction
|
||||
* fix for importing with some obj formatting
|
||||
* fix profile seeding for newer device record formats
|
||||
* fix workspace import / restore for some file formats
|
||||
* fix potential crash into stock during moves when parts are z bottom anchored
|
||||
* ~ refactor vertex replacement and widget update matrix tracking
|
||||
* ~ refactor cnc to use core slicer engine
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ const POLYS = base.polygons = {
|
|||
expand,
|
||||
expand_lines,
|
||||
points,
|
||||
length,
|
||||
route,
|
||||
union,
|
||||
inset,
|
||||
|
|
@ -52,6 +53,14 @@ const POLYS = base.polygons = {
|
|||
fingerprint
|
||||
};
|
||||
|
||||
function length(polys) {
|
||||
let length = 0;
|
||||
for (let p of polys) {
|
||||
length += p.deepLength;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
function setZ(polys, z) {
|
||||
for (let poly of polys) {
|
||||
poly.setZ(z);
|
||||
|
|
@ -376,13 +385,16 @@ function subtract(setA, setB, outA, outB, z, minArea, opt = {}) {
|
|||
*/
|
||||
function union(polys, minarea, all, opt = {}) {
|
||||
if (polys.length < 2) return polys;
|
||||
let lpre = length(polys);
|
||||
|
||||
if (opt.wasm && geo.wasm) {
|
||||
let min = minarea || 0.01;
|
||||
// let deepLength = polys.map(p => p.deepLength).reduce((a,v) => a+v);
|
||||
// if (deepLength < 15000)
|
||||
try {
|
||||
return geo.wasm.js.union(polys, polys[0].getZ()).filter(p => p.area() > min);
|
||||
let out = geo.wasm.js.union(polys, polys[0].getZ()).filter(p => p.area() > min);
|
||||
opt.changes = length(out) - lpre;
|
||||
return out;
|
||||
} catch (e) {
|
||||
console.log({union_fail: polys, minarea, all});
|
||||
}
|
||||
|
|
@ -419,6 +431,7 @@ function subtract(setA, setB, outA, outB, z, minArea, opt = {}) {
|
|||
if (out[i]) uset.push(out[i]);
|
||||
}
|
||||
|
||||
opt.changes = length(uset) - lpre;
|
||||
return uset;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -385,7 +385,11 @@ async function sliceZ(z, points, options = {}) {
|
|||
let groups = groupFn(lines, z, options);
|
||||
if (options.union) {
|
||||
// simplistic healing of non-manifold meshes
|
||||
groups = POLY.flatten(POLY.union(POLY.nest(groups), 0.1, true), null, true);
|
||||
let opt = { x: 1 };
|
||||
let union = POLY.union(POLY.nest(groups), 0.1, true, opt);
|
||||
// track total poly length changes to determine if healed
|
||||
rval.changes = opt.changes;
|
||||
groups = POLY.flatten(union, null, true);
|
||||
}
|
||||
rval.groups = groups;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,6 +159,7 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
|
|||
let points = widget.getPoints();
|
||||
let indices = [];
|
||||
let heights = [];
|
||||
let healed = false;
|
||||
|
||||
// handle z cutting (floor method) and base flattening
|
||||
let zPress = isBelt ? process.firstLayerFlatten || 0 : 0;
|
||||
|
|
@ -296,12 +297,16 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
|
|||
}).then((output) => {
|
||||
// post process slices and re-incorporate missing meta-data
|
||||
return output.slices.map(data => {
|
||||
let { z, clip, lines, groups } = data;
|
||||
let { z, clip, lines, groups, changes } = data;
|
||||
if (!data.tops) return null;
|
||||
let slice = newSlice(z).addTops(data.tops);
|
||||
slice.index = indices.indexOf(z);
|
||||
slice.height = heights[slice.index];
|
||||
slice.clips = clip;
|
||||
if (changes) {
|
||||
healed = true;
|
||||
slice.changes = changes;
|
||||
}
|
||||
if (process.xray) {
|
||||
slice.index = process.xrayi.shift();
|
||||
slice.lines = lines;
|
||||
|
|
@ -342,6 +347,11 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
|
|||
}
|
||||
|
||||
async function onSliceDone(slices) {
|
||||
// alert non-manifold parts
|
||||
if (healed) {
|
||||
onupdate(null, null, "part may not be manifold");
|
||||
}
|
||||
|
||||
// remove all empty slices above part but leave below
|
||||
// for multi-part (multi-extruder) setups where the void is ok
|
||||
// also reverse because slicing occurs bottom-up
|
||||
|
|
|
|||
|
|
@ -433,11 +433,13 @@ kiri.worker = {
|
|||
send.data({send_end: time()});
|
||||
}
|
||||
send.done({done: true});
|
||||
}, function(update, msg) {
|
||||
}, function(update, msg, alert) {
|
||||
now = time();
|
||||
if (now - last < 10 && update < 0.99) return;
|
||||
// on alert
|
||||
if (alert) send.data({ alert });
|
||||
// on update
|
||||
send.data({update: (0.05 + update * 0.95), updateStatus: msg});
|
||||
if (now - last < 10 && update < 0.99) return;
|
||||
if (update || msg) send.data({update: (0.05 + update * 0.95), updateStatus: msg});
|
||||
last = now;
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -161,7 +161,10 @@ function prepareSlices(callback, scale = 1, offset = 0) {
|
|||
// start next widget slice
|
||||
sliceNext();
|
||||
}
|
||||
}, (update, msg) => {
|
||||
}, (update, msg, alert) => {
|
||||
if (alert) {
|
||||
api.show.alert(alert);
|
||||
}
|
||||
if (msg && msg !== lastMsg) {
|
||||
let mark = Date.now();
|
||||
if (lastMsg) {
|
||||
|
|
@ -171,12 +174,14 @@ function prepareSlices(callback, scale = 1, offset = 0) {
|
|||
startTime = mark;
|
||||
}
|
||||
// on update
|
||||
track[widget.id] = (update || 0) * factor;
|
||||
totalProgress = 0;
|
||||
for (let w of slicing) {
|
||||
totalProgress += (track[w.id] || 0);
|
||||
if (update >= 0) {
|
||||
track[widget.id] = (update || 0) * factor;
|
||||
totalProgress = 0;
|
||||
for (let w of slicing) {
|
||||
totalProgress += (track[w.id] || 0);
|
||||
}
|
||||
show.progress(offset + (totalProgress / widgets.length) * scale, msg);
|
||||
}
|
||||
show.progress(offset + (totalProgress / widgets.length) * scale, msg);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -733,6 +733,9 @@ class Widget {
|
|||
|
||||
// executed from kiri.js
|
||||
kiri.client.slice(settings, this, function(reply) {
|
||||
if (reply.alert) {
|
||||
onupdate(null, null, reply.alert);
|
||||
}
|
||||
if (reply.update) {
|
||||
onupdate(reply.update, reply.updateStatus);
|
||||
}
|
||||
|
|
@ -774,8 +777,8 @@ class Widget {
|
|||
ondone();
|
||||
};
|
||||
|
||||
let catchupdate = function(progress, message) {
|
||||
onupdate(progress, message);
|
||||
let catchupdate = function(progress, message, alert) {
|
||||
onupdate(progress, message, alert);
|
||||
};
|
||||
|
||||
let drv = driver[settings.mode.toUpperCase()];
|
||||
|
|
|
|||
Loading…
Reference in a new issue