add new assembly preference for enabling wasm testing
This commit is contained in:
parent
8d8d80aa77
commit
841df7b5a9
16 changed files with 178 additions and 100 deletions
3
app.js
3
app.js
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
/** ******************************************************************
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
116
src/geo/wasm.js
116
src/geo/wasm.js
|
|
@ -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});
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -287,6 +287,12 @@ KIRI.work = {
|
|||
output(reply);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
wasm: function(enable) {
|
||||
send("wasm", {enable}, reply => {
|
||||
// console.log({wasm_worker_said: reply});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -692,6 +692,7 @@
|
|||
animesh: "200",
|
||||
healMesh: false,
|
||||
threaded: false,
|
||||
assembly: false,
|
||||
ortho: false,
|
||||
devel: false
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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" });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue