From 6f78d07d072f7a5c5162c673a80b9d79979252c6 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Mon, 21 Jun 2021 22:16:05 -0400 Subject: [PATCH] improve union speed with more efficient 2 in 2 out check --- src/geo/point.js | 4 ++++ src/geo/polygon.js | 48 +++++++++++++++++++++++++++++++++++-------- src/mode/fdm/slice.js | 4 ++-- web/kiri/lang/en.js | 2 +- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/geo/point.js b/src/geo/point.js index 4f3b1940..a4e18fdf 100644 --- a/src/geo/point.js +++ b/src/geo/point.js @@ -499,6 +499,10 @@ return this === p || (this.x === p.x && this.y === p.y && this.z === p.z); }; + PRO.isEqual2D = function(p) { + return this === p || (this.x === p.x && this.y === p.y); + }; + /** * returns true if points are close enough to be considered equivalent * diff --git a/src/geo/polygon.js b/src/geo/polygon.js index 2096faac..c38453c0 100644 --- a/src/geo/polygon.js +++ b/src/geo/polygon.js @@ -1751,6 +1751,27 @@ return null; } + function leftmost(p1, p2) { + if (!p1) { + return p2; + } + if (p1.x <= p2.x) { + if (p1.x < p2.x || (p1.x === p2.x && p1.y < p2.y)) { + return p2; + } + } + return p1; + } + + // return top-most, left-post point + PRO.leftmost = function() { + let tl = undefined; + for (let p of this.points) { + tl = leftmost(tl, p); + } + return tl; + }; + /** * return logical OR of two polygons' enclosed areas * @@ -1778,16 +1799,27 @@ let union = POLY().fromClipperTreeUnion(ctre, poly.getZ(), minarea); if (all) { if (union.length === 2) { - // TODO look for faster equivalence check. area? perimeter? - let src = [this, poly].sort((a,b) => { return a.area() - b.area() }); - let dst = union.sort((a,b) => { return a.area() - b.area() }); - if (src[0].isEquivalent(dst[0]) && src[1].isEquivalent(dst[1])) { - return null; + let src = [ this.leftmost(), poly.leftmost() ]; + let dst = [ union[0].leftmost(), union[1].leftmost() ]; + + if (leftmost(src[0], src[1]) === src[1]) { + src.reverse(); } - // only here is area sorting failed (same sizes) - if (src[0].isEquivalent(dst[1]) && src[1].isEquivalent(dst[0])) { - return null; + if (leftmost(dst[0], dst[1]) === dst[1]) { + dst.reverse(); } + + if ( + src[0].isEqual2D(dst[0]) && + src[1].isEqual2D(dst[1]) && + Math.abs(src[0].poly.area() - dst[0].poly.area()) < 0.01 && + Math.abs(src[1].poly.area() - dst[1].poly.area()) < 0.01 + ) { + return null; + } else if (debug) { + console.log("union debug", { src, dst }); + } + return null; } return union; } diff --git a/src/mode/fdm/slice.js b/src/mode/fdm/slice.js index 7bfbde46..05480502 100644 --- a/src/mode/fdm/slice.js +++ b/src/mode/fdm/slice.js @@ -255,7 +255,7 @@ let params = slice.params = getRangeParameters(settings, slice.index); let shellFrac = (params.sliceShells - (params.sliceShells | 0)); let sliceShells = params.sliceShells | 0; - if (ctrl.danger && shellFrac) { + if (shellFrac) { let v1 = shellFrac > 0.5 ? 1 - shellFrac : shellFrac; let v2 = 1 - v1; let parts = Math.round(v2/v1) + 1; @@ -264,11 +264,11 @@ sliceShells += rem >= trg ? 1 : 0; } let first = slice.index === 0; + let spaceMult = first ? spro.firstLayerLineMult || 1 : 1; let isBottom = slice.index < spro.sliceBottomLayers; let isTop = slice.index > slices.length - spro.sliceTopLayers-1; let isDense = params.sliceFillSparse > 0.98; let solidWidth = params.sliceFillWidth || 1; - let spaceMult = first ? spro.firstLayerLineMult || 1 : 1; if ((isBottom || ((isTop || isDense) && !vaseMode)) && !isSynth) { slice.solid = { solidWidth, diff --git a/web/kiri/lang/en.js b/web/kiri/lang/en.js index 8138f71e..9bda8f10 100644 --- a/web/kiri/lang/en.js +++ b/web/kiri/lang/en.js @@ -243,7 +243,7 @@ kiri.lang['en-us'] = { pt_heal_s: "heal mesh", pt_heal_l: ["attempt to heal","non-manifold meshes","adds to slicing time"], pt_thrd_s: "threaded", - pt_thrd_l: ["use parallel processin","when browser permits"], + pt_thrd_l: ["use parallel processing","when browser permits"], xp_menu: "exports",