add new assembly preference for enabling wasm testing

This commit is contained in:
Stewart Allen 2021-07-07 21:09:34 -04:00
commit 841df7b5a9
16 changed files with 178 additions and 100 deletions

3
app.js
View file

@ -287,7 +287,7 @@ const script = {
"add/three",
"add/class",
"geo/base",
// "geo/wasm",
"geo/wasm",
"geo/point",
"geo/points",
"geo/slope",
@ -331,6 +331,7 @@ const script = {
"add/array",
"add/class",
"geo/base",
"geo/wasm",
"geo/point",
"geo/points",
"geo/slope",

View file

@ -102,9 +102,9 @@
* @param {Point} p3
* @returns {boolean}
*/
function isCollinear(p1, p2, p3) {
return inCloseRange(area2(p1, p2, p3), -0.00001, 0.00001);
}
// function isCollinear(p1, p2, p3) {
// return inCloseRange(area2(p1, p2, p3), -0.00001, 0.00001);
// }
function pac(p1, p2) {
return (p2.x - p1.x) * (p2.y + p1.y);
@ -521,7 +521,7 @@
inRange,
isCloseTo,
inCloseRange,
isCollinear,
// isCollinear,
isClockwise,
isCounterClockwise,
doCombinations,

View file

@ -72,6 +72,7 @@
};
/**
* faulty when line doubles back at 180?
* @param {Line} line
* @returns {boolean}
*/
@ -85,7 +86,7 @@
d2x = (p4.x - p3.x),
d2y = (p4.y - p3.y);
return Math.abs( (d2y * d1x) - (d2x * d1y) ) < 0.000001;
return Math.abs( (d2y * d1x) - (d2x * d1y) ) < 0.0001;
};
/** ******************************************************************

View file

@ -1503,9 +1503,6 @@
* @returns {?Polygon[]} returns output array provided as input or new array if not provided
*/
PRO.offset = function(offset, output) {
// let offs = geo.poly.offset([this], -offset, this.getZ());
// if (output) output.appendAll(offs);
// return output || offs;
return POLY().expand([this], -offset, this.getZ(), output);
};

View file

@ -18,7 +18,7 @@
newPoint = BASE.newPoint,
numOrDefault = UTIL.numOrDefault;
BASE.polygons = {
const POLYS = BASE.polygons = {
rayIntersect,
alignWindings,
setWinding,
@ -527,18 +527,23 @@
mina = numOrDefault(opts.minArea, 0.1),
zed = opts.z || 0;
// setup offset
for (let poly of polys) {
// convert to clipper format
poly = poly.toClipper();
if (clean) poly = ClipperLib.Clipper.CleanPolygons(poly, CONF.clipperClean);
if (simple) poly = ClipperLib.Clipper.SimplifyPolygons(poly, fill);
coff.AddPaths(poly, join, type);
if (opts.wasm && geo.wasm) {
polys = geo.wasm.js.offset(polys, offs, zed);
} else {
// setup offset
for (let poly of polys) {
// convert to clipper format
poly = poly.toClipper();
if (clean) poly = ClipperLib.Clipper.CleanPolygons(poly, CONF.clipperClean);
if (simple) poly = ClipperLib.Clipper.SimplifyPolygons(poly, fill);
coff.AddPaths(poly, join, type);
}
// perform offset
coff.Execute(ctre, offs * CONF.clipper);
// convert back from clipper output format
polys = fromClipperTree(ctre, zed, null, null, mina);
}
// perform offset
coff.Execute(ctre, offs * CONF.clipper);
// convert back from clipper output format
polys = fromClipperTree(ctre, zed, null, null, mina);
// if specified, perform offset gap analysis
if (opts.gaps && polys.length) {
@ -583,15 +588,15 @@
* as performing subtractive analysis between initial layer shell (ref)
* and last offset (cmp) to produce gap candidates (for thinfill)
*/
function inset(polys, dist, count, z) {
function inset(polys, dist, count, z, wasm) {
let total = count;
let layers = [];
let ref = polys;
let depth = 0;
while (count-- > 0 && ref && ref.length) {
let off = offset(ref, -dist, {z});
let mid = offset(off, dist / 2, {z});
let cmp = offset(off, dist, {z});
let off = offset(ref, -dist, {z, wasm});
let mid = offset(off, dist / 2, {z, wasm});
let cmp = offset(off, dist, {z, wasm});
let gap = [];
let aref = ref.map(p => p.areaDeep()).reduce((a,p) => a +p);
let cref = cmp.length ? cmp.map(p => p.areaDeep()).reduce((a,p) => a + p) : 0;

View file

@ -5,7 +5,15 @@
// only active in workers
if (!self.window) (function() {
if (!self.geo) self.geo = {};
if (!self.geo) self.geo = {
enable,
disable,
count: {
offset: 0,
union: 0,
diff: 0
}
};
const factor = self.base.config.clipper;
const geo = self.geo;
@ -69,6 +77,7 @@ if (!self.window) (function() {
}
function polyOffset(polys, offset, z) {
geo.count.offset++;
let wasm = geo.wasm,
buffer = geo.wasm.shared,
pcount = writePolys(new DataWriter(wasm.heap, buffer), polys),
@ -78,6 +87,7 @@ if (!self.window) (function() {
}
function polyUnion(polys, z) {
geo.count.union++;
let wasm = geo.wasm,
buffer = geo.wasm.shared,
pcount = writePolys(new DataWriter(wasm.heap, buffer), polys),
@ -87,6 +97,7 @@ if (!self.window) (function() {
}
function polyDiff(polysA, polysB, z, AB, BA) {
geo.count.diff++;
let wasm = geo.wasm,
buffer = geo.wasm.shared,
writer = new DataWriter(wasm.heap, buffer),
@ -143,52 +154,65 @@ if (!self.window) (function() {
console.log('offs',{o1:o1[0].points});
}
fetch('/wasm/kiri-geo.wasm')
.then(response => response.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes, {
env: {
polygon: (a,b) => { console.log('polygon',a,b) },
point: (a,b) => { console.log('point',a,b) },
abc: (a,b,c) => { console.log('abc',a,b,c) }
},
wasi_snapshot_preview1: {
args_get: (count,bufsize) => { return 0 },
args_sizes_get: (count,bufsize) => { },
environ_get: (count,bufsize) => { return 0 },
environ_sizes_get: (count,bufsize) => { },
proc_exit: (code) => { return code }
}
}))
.then(results => {
let { module, instance } = results;
let { exports } = instance;
let heap = new DataView(exports.memory.buffer);
let wasm = geo.wasm = {
heap,
exports,
memory: exports.memory,
memmax: exports.memory.buffer.byteLength,
malloc: exports.mem_get,
free: exports.mem_clr,
set_debug: exports.set_debug
};
wasm.shared = wasm.malloc(1024 * 1024 * 10),
wasm.fn = {
diff: exports.poly_diff,
union: exports.poly_union,
offset: exports.poly_offset
};
wasm.js = {
diff: polyDiff,
union: polyUnion,
offset: polyOffset
};
if (debug) {
wasm.set_debug(1);
for (let i=0; i<100; i++) {
function enable() {
if (geo.wasm || geo._wasm) {
return;
}
geo._wasm = 'loading';
fetch('/wasm/kiri-geo.wasm')
.then(response => response.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes, {
env: {
polygon: (a,b) => { console.log('polygon',a,b) },
point: (a,b) => { console.log('point',a,b) },
abc: (a,b,c) => { console.log('abc',a,b,c) }
},
wasi_snapshot_preview1: {
args_get: (count,bufsize) => { return 0 },
args_sizes_get: (count,bufsize) => { },
environ_get: (count,bufsize) => { return 0 },
environ_sizes_get: (count,bufsize) => { },
proc_exit: (code) => { return code }
}
}))
.then(results => {
// console.log({enabled: geo.wasm});
delete geo._wasm;
let { module, instance } = results;
let { exports } = instance;
let heap = new DataView(exports.memory.buffer);
let wasm = geo.wasm = {
heap,
exports,
memory: exports.memory,
memmax: exports.memory.buffer.byteLength,
malloc: exports.mem_get,
free: exports.mem_clr,
set_debug: exports.set_debug
};
wasm.shared = wasm.malloc(1024 * 1024 * 32),
wasm.fn = {
diff: exports.poly_diff,
union: exports.poly_union,
offset: exports.poly_offset
};
wasm.js = {
diff: polyDiff,
union: polyUnion,
offset: polyOffset
};
if (debug) {
wasm.set_debug(1);
runTests();
}
}
});
});
}
function disable() {
if (geo.wasm) {
delete geo.wasm;
// console.log({disabled: geo});
}
}
})();

View file

@ -287,6 +287,12 @@ KIRI.work = {
output(reply);
}
});
},
wasm: function(enable) {
send("wasm", {enable}, reply => {
// console.log({wasm_worker_said: reply});
});
}
};

View file

@ -692,6 +692,7 @@
animesh: "200",
healMesh: false,
threaded: false,
assembly: false,
ortho: false,
devel: false
},

View file

@ -142,6 +142,9 @@
let control = settings().controller;
let isDark = control.dark;
let doAlert = UI.ortho.checked !== control.ortho;
if (control.assembly != UI.assembly.checked) {
KIRI.client.wasm(UI.assembly.checked);
}
control.decals = UI.decals.checked;
control.danger = UI.danger.checked;
control.showOrigin = UI.showOrigin.checked;
@ -158,6 +161,7 @@
control.decimate = UI.decimate.checked;
control.healMesh = UI.healMesh.checked;
control.threaded = UI.threaded.checked;
control.assembly = UI.assembly.checked;
control.ortho = UI.ortho.checked;
control.devel = UI.devel.checked;
SPACE.view.setZoom(control.reverseZoom, control.zoomSpeed);
@ -1647,6 +1651,7 @@
decimate: UC.newBoolean(LANG.pt_deci_s, booleanSave, {title: LANG.pt_deci_l}),
healMesh: UC.newBoolean(LANG.pt_heal_s, booleanSave, {title: LANG.pt_heal_l}),
threaded: UC.newBoolean(LANG.pt_thrd_s, booleanSave, {title: LANG.pt_thrd_l, modes:FDM_SLA}),
assembly: UC.newBoolean(LANG.pt_assy_s, booleanSave, {title: LANG.pt_assy_l, modes:FDM_SLA}),
prefadd: UC.checkpoint($('prefs-add')),
@ -2439,6 +2444,7 @@
UI.decimate.checked = control.decimate;
UI.healMesh.checked = control.healMesh;
UI.threaded.checked = control.threaded;
UI.assembly.checked = control.assembly;
UI.ortho.checked = control.ortho;
UI.devel.checked = control.devel;
lineTypeSave();
@ -2471,6 +2477,9 @@
// update everything dependent on the platform size
platform.update_size();
// load wasm if indicated
KIRI.client.wasm(control.assembly);
};
UI.sync();

View file

@ -102,6 +102,14 @@ const funcs = {
reply({ seq, output: CODEC.encode(output) });
},
wasm: data => {
if (data.enable) {
geo.enable();
} else {
geo.disable();
}
},
bad: (data, seq) => {
reply({ seq, error: "invalid command" });
}

View file

@ -847,7 +847,10 @@
// merge collinear lines
for (let point of points) {
if (point.group.length != 2) continue;
// only merge when point connects to exactly one other point
if (point.group.length != 2) {
continue;
}
let l1 = point.group[0],
l2 = point.group[1];
if (l1.isCollinear(l2)) {

View file

@ -173,6 +173,15 @@ KIRI.minions = {
};
minion.postMessage(qrec.work, qrec.direct);
}
},
wasm: function(enable) {
for (let minion of minions) {
minion.postMessage({
cmd: "wasm",
enable
});
}
}
};
@ -727,6 +736,16 @@ KIRI.worker = {
}).then(output => {
send.done(output);
});
},
wasm: function(data, send) {
if (data.enable) {
geo.enable();
} else {
geo.disable();
}
minwork.wasm(data.enable);
send.done({ wasm: data });
}
};

View file

@ -402,7 +402,6 @@
addto.belt.touch = false;
let z = addto.z;
let y = z - smin - (nozzleSize / 2);
// let splat = BASE.newPolygon().add(wb.min.x, y, z).add(wb.max.x, y, z).setOpen();
let splat = BASE.newPolygon().add(minx, y, z).add(maxx, y, z).setOpen();
let snew = addto.addTop(splat).fill_sparse = [ splat ];
adds.push(snew);
@ -726,7 +725,7 @@
if (opt.danger && opt.thin) {
top.thin_fill = [];
top.fill_sparse = [];
let layers = POLY.inset(top_poly, offsetN, count, z);
let layers = POLY.inset(top_poly, offsetN, count, z, true);
last = layers.last().mid;
top.shells = layers.map(r => r.mid).flat();
top.gaps = layers.map(r => r.gap).flat();
@ -740,7 +739,7 @@
}
} else if (opt.thin) {
top.thin_fill = [];
let oso = {z, count, gaps: [], outs: [], minArea: 0.05};
let oso = {z, count, gaps: [], outs: [], minArea: 0.05, wasm: true};
POLY.offset(top_poly, [-offset1, -offsetN], oso);
oso.outs.forEach((polys, i) => {
@ -762,7 +761,7 @@
// slice.solids.trimmed = slice.solids.trimmed || [];
oso.gaps.forEach((polys, i) => {
let off = (i == 0 ? offset1 : offsetN);
polys = POLY.offset(polys, -off * 0.8, {z, minArea: 0});
polys = POLY.offset(polys, -off * 0.8, {z, minArea: 0, wasm: true});
top.thin_fill.appendAll(cullIntersections(
fillArea(polys, 45, off/2, [], 0.01, off*2),
fillArea(polys, 135, off/2, [], 0.01, off*2),
@ -771,30 +770,33 @@
});
} else {
// standard wall offsetting strategy
POLY.expand(
top_poly, // reference polygon(s)
-offset1, // first inset distance
z, // set new polys to this z
top.shells, // accumulator array
count, // number of insets to perform
-offsetN, // subsequent inset distance
// on each new offset trace ...
function(polys, countNow) {
last = polys;
// mark each poly with depth (offset #) starting at 0
polys.forEach(function(p) {
p.depth = count - countNow;
if (p.fill_off) p.fill_off.forEach(function(pi) {
// use negative offset for inners
pi.depth = -(count - countNow);
});
if (p.inner) {
for (let pi of p.inner) {
pi.depth = p.depth;
POLY.offset(
top_poly,
[-offset1, -offsetN],
{
z,
outs: top.shells,
flat: true,
wasm: true,
call: (polys, onCount) => {
last = polys;
// mark each poly with depth (offset #) starting at 0
for (let p of polys) {
p.depth = count - onCount;
if (p.fill_off) p.fill_off.forEach(function(pi) {
// use negative offset for inners
pi.depth = -(count - onCount);
});
// mark inner depth to match parent
if (p.inner) {
for (let pi of p.inner) {
pi.depth = p.depth;
}
}
}
});
});
}
}
);
}
}
} else {
@ -1372,7 +1374,7 @@
// angle based on width/height ratio
let angle = (poly.bounds.width() / poly.bounds.height() > 1) ? 90 : 0;
// inset support poly for fill lines 33% of nozzle width
let inset = POLY.offset([poly], -linewidth/3, {flat: true, z});
let inset = POLY.offset([poly], -linewidth/3, {flat: true, z, wasm: true});
// do the fill
if (inset && inset.length > 0) {
doFillArea(promises, inset, angle, spacing, poly.fill = []);

Binary file not shown.

View file

@ -4,7 +4,7 @@ kiri-sla.wasm: kiri-sla.c
emcc --no-entry -o kiri-sla.wasm kiri-sla.c -O3 -s ERROR_ON_UNDEFINED_SYMBOLS=0
kiri-geo.wasm: kiri-geo.cpp
emcc --no-entry -o kiri-geo.wasm clipper.cpp kiri-geo.cpp -Oz -s ERROR_ON_UNDEFINED_SYMBOLS=0
emcc --no-entry -o kiri-geo.wasm clipper.cpp kiri-geo.cpp -Oz -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s TOTAL_MEMORY=40mb
kiri-ani.wasm: kiri-ani.c
emcc --no-entry -o kiri-ani.wasm kiri-ani.c -O3 -s ERROR_ON_UNDEFINED_SYMBOLS=0

View file

@ -246,6 +246,8 @@ kiri.lang['en-us'] = {
pt_heal_l: ["attempt to heal","non-manifold meshes","adds to slicing time"],
pt_thrd_s: "threaded",
pt_thrd_l: ["use parallel processing","when browser permits"],
pt_assy_s: "assembly",
pt_assy_l: ["use web assembly","when browser permits"],
xp_menu: "exports",