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` add option for op-major ordering (instead of part major)
|
||||||
* `F` animate only selected range (as an option)
|
* `F` animate only selected range (as an option)
|
||||||
* `F` add `plunge max` to contouring that can override z feed limit
|
* `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` 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` 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
|
* `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
|
## 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
|
* fix potential crash into stock during moves when parts are z bottom anchored
|
||||||
* ~ refactor vertex replacement and widget update matrix tracking
|
* ~ refactor vertex replacement and widget update matrix tracking
|
||||||
* ~ refactor cnc to use core slicer engine
|
* ~ refactor cnc to use core slicer engine
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ const POLYS = base.polygons = {
|
||||||
expand,
|
expand,
|
||||||
expand_lines,
|
expand_lines,
|
||||||
points,
|
points,
|
||||||
|
length,
|
||||||
route,
|
route,
|
||||||
union,
|
union,
|
||||||
inset,
|
inset,
|
||||||
|
|
@ -52,6 +53,14 @@ const POLYS = base.polygons = {
|
||||||
fingerprint
|
fingerprint
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function length(polys) {
|
||||||
|
let length = 0;
|
||||||
|
for (let p of polys) {
|
||||||
|
length += p.deepLength;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
function setZ(polys, z) {
|
function setZ(polys, z) {
|
||||||
for (let poly of polys) {
|
for (let poly of polys) {
|
||||||
poly.setZ(z);
|
poly.setZ(z);
|
||||||
|
|
@ -376,13 +385,16 @@ function subtract(setA, setB, outA, outB, z, minArea, opt = {}) {
|
||||||
*/
|
*/
|
||||||
function union(polys, minarea, all, opt = {}) {
|
function union(polys, minarea, all, opt = {}) {
|
||||||
if (polys.length < 2) return polys;
|
if (polys.length < 2) return polys;
|
||||||
|
let lpre = length(polys);
|
||||||
|
|
||||||
if (opt.wasm && geo.wasm) {
|
if (opt.wasm && geo.wasm) {
|
||||||
let min = minarea || 0.01;
|
let min = minarea || 0.01;
|
||||||
// let deepLength = polys.map(p => p.deepLength).reduce((a,v) => a+v);
|
// let deepLength = polys.map(p => p.deepLength).reduce((a,v) => a+v);
|
||||||
// if (deepLength < 15000)
|
// if (deepLength < 15000)
|
||||||
try {
|
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) {
|
} catch (e) {
|
||||||
console.log({union_fail: polys, minarea, all});
|
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]);
|
if (out[i]) uset.push(out[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opt.changes = length(uset) - lpre;
|
||||||
return uset;
|
return uset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -385,7 +385,11 @@ async function sliceZ(z, points, options = {}) {
|
||||||
let groups = groupFn(lines, z, options);
|
let groups = groupFn(lines, z, options);
|
||||||
if (options.union) {
|
if (options.union) {
|
||||||
// simplistic healing of non-manifold meshes
|
// 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;
|
rval.groups = groups;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,7 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
|
||||||
let points = widget.getPoints();
|
let points = widget.getPoints();
|
||||||
let indices = [];
|
let indices = [];
|
||||||
let heights = [];
|
let heights = [];
|
||||||
|
let healed = false;
|
||||||
|
|
||||||
// handle z cutting (floor method) and base flattening
|
// handle z cutting (floor method) and base flattening
|
||||||
let zPress = isBelt ? process.firstLayerFlatten || 0 : 0;
|
let zPress = isBelt ? process.firstLayerFlatten || 0 : 0;
|
||||||
|
|
@ -296,12 +297,16 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
|
||||||
}).then((output) => {
|
}).then((output) => {
|
||||||
// post process slices and re-incorporate missing meta-data
|
// post process slices and re-incorporate missing meta-data
|
||||||
return output.slices.map(data => {
|
return output.slices.map(data => {
|
||||||
let { z, clip, lines, groups } = data;
|
let { z, clip, lines, groups, changes } = data;
|
||||||
if (!data.tops) return null;
|
if (!data.tops) return null;
|
||||||
let slice = newSlice(z).addTops(data.tops);
|
let slice = newSlice(z).addTops(data.tops);
|
||||||
slice.index = indices.indexOf(z);
|
slice.index = indices.indexOf(z);
|
||||||
slice.height = heights[slice.index];
|
slice.height = heights[slice.index];
|
||||||
slice.clips = clip;
|
slice.clips = clip;
|
||||||
|
if (changes) {
|
||||||
|
healed = true;
|
||||||
|
slice.changes = changes;
|
||||||
|
}
|
||||||
if (process.xray) {
|
if (process.xray) {
|
||||||
slice.index = process.xrayi.shift();
|
slice.index = process.xrayi.shift();
|
||||||
slice.lines = lines;
|
slice.lines = lines;
|
||||||
|
|
@ -342,6 +347,11 @@ FDM.slice = function(settings, widget, onupdate, ondone) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onSliceDone(slices) {
|
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
|
// remove all empty slices above part but leave below
|
||||||
// for multi-part (multi-extruder) setups where the void is ok
|
// for multi-part (multi-extruder) setups where the void is ok
|
||||||
// also reverse because slicing occurs bottom-up
|
// also reverse because slicing occurs bottom-up
|
||||||
|
|
|
||||||
|
|
@ -433,11 +433,13 @@ kiri.worker = {
|
||||||
send.data({send_end: time()});
|
send.data({send_end: time()});
|
||||||
}
|
}
|
||||||
send.done({done: true});
|
send.done({done: true});
|
||||||
}, function(update, msg) {
|
}, function(update, msg, alert) {
|
||||||
now = time();
|
now = time();
|
||||||
if (now - last < 10 && update < 0.99) return;
|
// on alert
|
||||||
|
if (alert) send.data({ alert });
|
||||||
// on update
|
// 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;
|
last = now;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,10 @@ function prepareSlices(callback, scale = 1, offset = 0) {
|
||||||
// start next widget slice
|
// start next widget slice
|
||||||
sliceNext();
|
sliceNext();
|
||||||
}
|
}
|
||||||
}, (update, msg) => {
|
}, (update, msg, alert) => {
|
||||||
|
if (alert) {
|
||||||
|
api.show.alert(alert);
|
||||||
|
}
|
||||||
if (msg && msg !== lastMsg) {
|
if (msg && msg !== lastMsg) {
|
||||||
let mark = Date.now();
|
let mark = Date.now();
|
||||||
if (lastMsg) {
|
if (lastMsg) {
|
||||||
|
|
@ -171,12 +174,14 @@ function prepareSlices(callback, scale = 1, offset = 0) {
|
||||||
startTime = mark;
|
startTime = mark;
|
||||||
}
|
}
|
||||||
// on update
|
// on update
|
||||||
|
if (update >= 0) {
|
||||||
track[widget.id] = (update || 0) * factor;
|
track[widget.id] = (update || 0) * factor;
|
||||||
totalProgress = 0;
|
totalProgress = 0;
|
||||||
for (let w of slicing) {
|
for (let w of slicing) {
|
||||||
totalProgress += (track[w.id] || 0);
|
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
|
// executed from kiri.js
|
||||||
kiri.client.slice(settings, this, function(reply) {
|
kiri.client.slice(settings, this, function(reply) {
|
||||||
|
if (reply.alert) {
|
||||||
|
onupdate(null, null, reply.alert);
|
||||||
|
}
|
||||||
if (reply.update) {
|
if (reply.update) {
|
||||||
onupdate(reply.update, reply.updateStatus);
|
onupdate(reply.update, reply.updateStatus);
|
||||||
}
|
}
|
||||||
|
|
@ -774,8 +777,8 @@ class Widget {
|
||||||
ondone();
|
ondone();
|
||||||
};
|
};
|
||||||
|
|
||||||
let catchupdate = function(progress, message) {
|
let catchupdate = function(progress, message, alert) {
|
||||||
onupdate(progress, message);
|
onupdate(progress, message, alert);
|
||||||
};
|
};
|
||||||
|
|
||||||
let drv = driver[settings.mode.toUpperCase()];
|
let drv = driver[settings.mode.toUpperCase()];
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue