diff --git a/src/geo/polygons.js b/src/geo/polygons.js index 64e954f4..6d6a1bf0 100644 --- a/src/geo/polygons.js +++ b/src/geo/polygons.js @@ -299,13 +299,14 @@ min = minArea || 0.1, out = []; - function filter(from, to) { + function filter(from, to = []) { from.forEach(function(poly) { if (poly.area() >= min) { to.push(poly); out.push(poly); } }); + return to; } // expensive but worth it? @@ -319,6 +320,9 @@ cleanClipperTree(ctre); filter(fromClipperTree(ctre, z, null, null, min), outA); } + let woutA = filter(geo.poly.diff(setA, setB, z)); + // outA.appendAll(woutA); + // console.log({outA, woutA}); } if (outB) { @@ -334,6 +338,9 @@ cleanClipperTree(ctre); filter(fromClipperTree(ctre, z, null, null, min), outB); } + let woutB = filter(geo.poly.diff(setB, setA, z)); + // outB.appendAll(woutB); + // console.log({outB, woutB}); } return out; diff --git a/src/geo/wasm.js b/src/geo/wasm.js index 8820a503..f2e39483 100644 --- a/src/geo/wasm.js +++ b/src/geo/wasm.js @@ -11,6 +11,7 @@ if (!self.window) (function() { const geo = self.geo; geo.poly = { + diff: polyDiff, union: polyUnion, offset: polyOffset }; @@ -94,6 +95,29 @@ if (!self.window) (function() { return polyNest(out); } + function polyDiff(polysA, polysB, z) { + let wasm = geo.wasm, + memat = wasm.malloc(1024 * 128), + writer = new DataWriter(wasm.heap, memat), + pcountA = 0, + pcountB = 0; + polysA.forEach(poly => pcountA += writePoly(writer, poly)); + polysB.forEach(poly => pcountB += writePoly(writer, poly)); + let resat = wasm.diff(memat, pcountA, pcountB, (pcountA + pcountB) * 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) => { @@ -149,6 +173,7 @@ if (!self.window) (function() { malloc: exports.mem_get, start: exports._start, free: exports.mem_clr, + diff: exports.poly_diff, union: exports.poly_union, offset: exports.poly_offset }; diff --git a/wasm/kiri-geo.cpp b/wasm/kiri-geo.cpp index e04d8511..cc3057c9 100644 --- a/wasm/kiri-geo.cpp +++ b/wasm/kiri-geo.cpp @@ -94,7 +94,7 @@ Uint32 poly_offset(Uint32 memat, Uint32 polys, float offset) { } __attribute__ ((export_name("poly_union"))) -Uint32 poly_union(Uint32 memat, Uint32 polys) { +Uint32 poly_union(Uint32 memat, Uint32 polys, float offset) { using namespace ClipperLib; @@ -116,9 +116,72 @@ Uint32 poly_union(Uint32 memat, Uint32 polys) { } Clipper clip; - clip.AddPath(ins[0], ptSubject, true); - clip.AddPath(ins[1], ptClip, true); - clip.Execute(ctUnion, outs, pftEvenOdd, pftEvenOdd); + clip.AddPaths(ins, ptSubject, true); + clip.Execute(ctUnion, outs); + + 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; +} + + + +__attribute__ ((export_name("poly_diff"))) +Uint32 poly_diff(Uint32 memat, Uint32 polysA, Uint32 polysB, float offset) { + + using namespace ClipperLib; + + Paths inA(polysA); + Paths inB(polysB); + Paths outs; + Uint32 pos = memat; + + for (Uint32 poly = 0; poly < polysA; poly++ ) { + 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; + inA[poly] << IntPoint(ip->x, ip->y); + } + poly++; + } + + for (Uint32 poly = 0; poly < polysB; poly++ ) { + 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; + inB[poly] << IntPoint(ip->x, ip->y); + } + poly++; + } + + Clipper clip; + clip.AddPaths(inA, ptSubject, true); + clip.AddPaths(inB, ptClip, true); + clip.Execute(ctDifference, outs, pftEvenOdd, pftEvenOdd); Uint32 resat = pos; diff --git a/wasm/kiri-geo.wasm b/wasm/kiri-geo.wasm index d4525db1..332c1ef1 100755 Binary files a/wasm/kiri-geo.wasm and b/wasm/kiri-geo.wasm differ