fixes #206 empty surfaces with multi-part and pocket

This commit is contained in:
Stewart Allen 2022-06-05 19:17:43 -04:00
commit 0e7d01c8fa
6 changed files with 98 additions and 48 deletions

View file

@ -74,6 +74,8 @@
* `B` need to force cut line at synthetic z bottom (midlines, etc)
* `B` contour does not honor clip to stock
* `F` add pause operation with optional gcode
* `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` roughing flats should be constrained to flat region, not create a layer

View file

@ -1005,10 +1005,10 @@ class OpPocket extends CamOp {
}
}
}
let surfaces = op.surfaces[widget.id];
let surfaces = op.surfaces[widget.id] || [];
let vert = widget.getVertices().array.map(v => v.round(4));
let prog = 0, pinc= 1 / surfaces.length;
for (let surface of surfaces || []) {
for (let surface of surfaces) {
let outline = [];
let faces = CAM.surface_find(widget, [surface]);
let zmin = Infinity;
@ -1030,7 +1030,7 @@ class OpPocket extends CamOp {
if (false) newSliceOut(zmin).output()
.setLayer("pocket area", {line: 0x1188ff}, false)
.addPolys(outline)
clearZ(outline, zmin, down);
clearZ(outline, zmin + 0.0001, down);
progress(prog += pinc, "pocket");
}
}

View file

@ -15,19 +15,54 @@ load.TMF = {
parseAsync
};
load.XML = {
query
};
let { BufferAttribute, Matrix4 } = THREE;
function query(node, path, fn) {
let collect = false;
let match = path[0];
if (match[0] === '+') {
match = match.slice(1);
collect = true;
// simple query api for map structures
function query_map(node, path, fn) {
let collect = {};
let match = path[0].split('|').map(key => {
if (key[0] === '+') {
key = key.slice(1);
collect[key] = true;
}
return key;
});
for (let [tag, value] of Object.entries(node)) {
if (!Array.isArray(value)) {
value = [ value ];
}
if (match.indexOf(tag) >= 0) {
for (let node of value) {
if (collect[tag]) {
fn(tag, node);
}
if (path.length > 1) {
query(node, path.slice(1), fn);
}
}
}
}
}
// simple query api for xml structures
function query(node, path, fn) {
let collect = {};
let match = path[0].split('|').map(key => {
if (key[0] === '+') {
key = key.slice(1);
collect[key] = true;
}
return key;
});
for (let child of [...node.childNodes]) {
if (child.tagName === match) {
if (collect) {
fn(match, child);
let { tagName } = child;
if (match.indexOf(tagName) >= 0) {
if (collect[tagName]) {
fn(tagName, child);
}
if (path.length > 1) {
query(child, path.slice(1), fn);

View file

@ -15,7 +15,47 @@ if (load.File) return;
// dep: load.png
gapp.register('load.file', []);
const types = {
stl(data, file, resolve, reject) {
resolve([{
mesh: new load.STL().parse(data), file
}]);
},
obj(data, file, resolve, reject) {
resolve(load.OBJ.parse(data).map(m => {
return { mesh: m.toFloat32(), file: nameOf(file, m.name, 1) }
}));
},
"3mf"(data, file, resolve, reject) {
let i = 1;
load.TMF.parseAsync(data).then((meshes) => {
resolve(meshes.map(m => {
return { mesh: m.faces.toFloat32(), file: nameOf(file, m.name, i++) }
}));
});
},
svg(data, file, resolve, reject) {
resolve(load.SVG.parse(data).map(m => { return {mesh: m.toFloat32(), file} }));
},
png(data, file, resolve, reject) {
load.PNG.parse(data, {
...opt,
done(data) {
resolve({ mesh: data, file });
}
});
}
};
const as_buffer = [ "stl", "png", "3mf" ];
load.File = {
types,
as_buffer,
load_data,
load: load_file
};
@ -31,39 +71,11 @@ function nameOf(file, part, i) {
function load_data(data, file, ext, opt = {}) {
ext = ext || name.toLowerCase().split('.').pop();
return new Promise((resolve, reject) => {
let i = 1;
switch (ext) {
case "stl":
resolve([{
mesh: new load.STL().parse(data), file
}]);
break;
case "obj":
resolve(load.OBJ.parse(data).map(m => {
return { mesh: m.toFloat32(), file: nameOf(file, m.name, i++) }
}));
break;
case "3mf":
load.TMF.parseAsync(data).then((meshes) => {
resolve(meshes.map(m => {
return { mesh: m.faces.toFloat32(), file: nameOf(file, m.name, i++) }
}));
});
break;
case "svg":
resolve(load.SVG.parse(data).map(m => { return {mesh: m.toFloat32(), file} }));
break;
case "png":
load.PNG.parse(data, {
...opt,
done(data) {
resolve({ mesh: data, file });
}
});
break;
default:
reject(`unknown file type: "${ext}" from ${file}`);
break;
let fn = types[ext];
if (fn) {
fn(data, file, resolve, reject);
} else {
reject(`unknown file type: "${ext}" from ${file}`);
}
});
}
@ -85,7 +97,7 @@ function load_file(file, opt) {
.then(data => resolve(data))
.catch(e => reject(e));
};
if (["stl","png","3mf"].indexOf(ext) >= 0) {
if (as_buffer.indexOf(ext) >= 0) {
reader.readAsArrayBuffer(reader.file);
} else {
reader.readAsBinaryString(reader.file);

View file

@ -522,7 +522,8 @@ function load_files_opt(files, opt) {
// add object loader
function space_load(data) {
mesh.api.group.new(data.flat().map(el => new mesh.model(el)))
if (data && data.length && (data = data.flat()).length)
mesh.api.group.new(data.map(el => new mesh.model(el)))
.promote()
.focus();
}

View file

@ -141,7 +141,7 @@
</script>
</head>
<body onload="onload()">
<h2 id="title">Kiri:Moto Javascript Engine API</h2>
<h2 id="title">Kiri:Moto Javascript Engine <a href="https://docs.grid.space/projects/kiri-moto/apis">API</a></h2>
<div id="demo">
<div id="jcode">
<div id="jhead">javascript</div>