diff --git a/src/geo/polygon.js b/src/geo/polygon.js index c38453c0..f5c22757 100644 --- a/src/geo/polygon.js +++ b/src/geo/polygon.js @@ -1817,7 +1817,14 @@ ) { return null; } else if (debug) { - console.log("union debug", { src, dst }); + console.log("union debug", { + src, + dst, + d0: Math.abs(src[0].poly.area() - dst[0].poly.area()), + d1: Math.abs(src[1].poly.area() - dst[1].poly.area()), + m0: src[0].isEqual2D(dst[0]), + m1: src[1].isEqual2D(dst[1]) + }); } return null; } diff --git a/src/geo/wasm.js b/src/geo/wasm.js index 5a9cc260..8820a503 100644 --- a/src/geo/wasm.js +++ b/src/geo/wasm.js @@ -10,7 +10,10 @@ if (!self.window) (function() { const factor = self.base.config.clipper; const geo = self.geo; - geo.poly = { offset : polyOffset }; + geo.poly = { + union: polyUnion, + offset: polyOffset + }; function log() { console.log(...arguments); @@ -70,6 +73,27 @@ if (!self.window) (function() { return polyNest(out); } + function polyUnion(polys, z) { + let wasm = geo.wasm, + memat = wasm.malloc(1024 * 128), + writer = new DataWriter(wasm.heap, memat), + pcount = 0; + polys.forEach(poly => pcount += writePoly(writer, poly)); + let resat = wasm.union(memat, pcount, pcount * factor), + reader = new DataReader(wasm.heap, resat), + out = []; + for (;;) { + let poly = readPoly(reader, z); + if (poly) { + out.push(poly); + } else { + break; + } + } + wasm.free(memat); + return polyNest(out); + } + // nest closed polygons without existing parent / child relationships function polyNest(polys) { polys.sort((a,b) => { @@ -120,14 +144,16 @@ if (!self.window) (function() { let heap = new DataView(exports.memory.buffer); let wasm = geo.wasm = { heap, + exports, memory: exports.memory, - start: exports._start, - offset: exports.poly_offset, malloc: exports.mem_get, - free: exports.mem_clr + start: exports._start, + free: exports.mem_clr, + union: exports.poly_union, + offset: exports.poly_offset }; - wasm.start(); + // wasm.start(); }); })(); diff --git a/wasm/kiri-geo.cpp b/wasm/kiri-geo.cpp index bb19c418..e04d8511 100644 --- a/wasm/kiri-geo.cpp +++ b/wasm/kiri-geo.cpp @@ -92,3 +92,53 @@ Uint32 poly_offset(Uint32 memat, Uint32 polys, float offset) { return resat; } + +__attribute__ ((export_name("poly_union"))) +Uint32 poly_union(Uint32 memat, Uint32 polys) { + + using namespace ClipperLib; + + Paths ins(polys); + Paths outs; + Uint32 pos = memat; + Uint16 poly = 0; + + while (poly < polys) { + struct length16 *ls = (struct length16 *)(mem + pos); + Uint16 points = ls->length; + pos += 2; + while (points-- > 0) { + struct point32 *ip = (struct point32 *)(mem + pos); + pos += 8; + ins[poly] << IntPoint(ip->x, ip->y); + } + poly++; + } + + Clipper clip; + clip.AddPath(ins[0], ptSubject, true); + clip.AddPath(ins[1], ptClip, true); + clip.Execute(ctUnion, outs, pftEvenOdd, pftEvenOdd); + + Uint32 resat = pos; + + for (Path po : outs) { + struct length16 *ls = (struct length16 *)(mem + pos); + ls->length = po.size(); + pos += 2; + for (IntPoint pt : po) { + struct point32 *ip = (struct point32 *)(mem + pos); + ip->x = (int)pt.X; + ip->y = (int)pt.Y; + pos += 8; + } + } + + // null terminate + struct length16 *ls = (struct length16 *)(mem + pos); + ls->length = 0; + + clip.Clear(); + + return resat; +} diff --git a/wasm/kiri-geo.wasm b/wasm/kiri-geo.wasm index a8169a9b..d4525db1 100755 Binary files a/wasm/kiri-geo.wasm and b/wasm/kiri-geo.wasm differ