From df8feb8ae7dda345dfeda59b8758f76408ea7ef4 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Thu, 27 Jan 2022 15:12:43 -0500 Subject: [PATCH] more modular functionality for base slicer --- src/geo/slicer.js | 73 ++++++++++++++++++++++++++++++++--------------- src/main/mesh.js | 2 +- src/mesh/work.js | 4 +-- 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/src/geo/slicer.js b/src/geo/slicer.js index b89731c8..bc1f3543 100644 --- a/src/geo/slicer.js +++ b/src/geo/slicer.js @@ -3,7 +3,8 @@ "use strict"; /** - * Basic slice and line connection + * basic slice and line connection. In future, replace kiri's fdm and cam slicers + * with wrappers on this one. */ (function() { @@ -13,6 +14,10 @@ let { config, util, polygons } = base let { newOrderedLine, newPolygon, newPoint } = base; + function dval(v, dv) { + return v !== undefined ? v : dv; + } + /** * Given an array of points as triples, a bounding box and a set of * slicing controls, emit an array of Slice objects to the ondone() @@ -33,7 +38,9 @@ zScale, // bucket span in z units zSum = 0.0, // sanity check that points enclose non-zere volume buckets = [], // banded/grouped faces to speed up slice/search + bucketMax = options.overlap || 0.75, onupdate = options.onupdate || function() {}, + sliceFn = dval(options.slicer, sliceZ), { debug, flat, autoDim } = options, i, j, p1, p2, p3; @@ -136,8 +143,9 @@ } if (bucketCount > 1) { + let failAt = (points.length * bucketMax) | 0, bucket; // copy triples into all matching z-buckets - for (i = 0; i < points.length;) { + outer: for (i = 0; i < points.length;) { p1 = points[i++]; p2 = points[i++]; p3 = points[i++]; @@ -146,19 +154,31 @@ bm = Math.floor(zm * zScale), bM = Math.ceil(zM * zScale); // add point to all buckets in range - for (j = bm; j <= bM; j++) { - buckets[j].points.push(p1); - buckets[j].points.push(p2); - buckets[j].points.push(p3); + for (j = bm; j < bM; j++) { + bucket = buckets[j].points; + bucket.push(p1); + bucket.push(p2); + bucket.push(p3); + // fail if single bucket exceeds threshold + if (bucket.length > failAt) { + if (debug) console.log({ bucketFail: bucket.length }); + bucketCount = 1; + break outer; + } } } - } else { - buckets.push({ points, slices: [] }); + } + + // fallback if we can't partition point space + if (bucketCount === 1) { + buckets = [{ points, slices: [] }]; + console.log({fallback: buckets}); } // create buckets data structure for (let z of zIndexes) { - buckets[Math.floor((z - zMin) * zScale)].slices.push(z); + let index = bucketCount > 1 ? Math.floor((z - zMin) * zScale) : 0; + buckets[index].slices.push(z); onupdate((i / zIndexes.length) * 0.1); } @@ -166,18 +186,20 @@ let output = []; let count = 0; let opt = { ...options, zMin, zMax }; + for (let bucket of buckets) { let { points, slices } = bucket; for (let z of slices) { - output.push(sliceZ(z, points, opt)); + output.push(await sliceFn(z, points, opt)); onupdate(0.1 + (count++ / zIndexes.length) * 0.9); } } + return output; } // create slices from each bucketed region - let slices = await sliceBuckets(); + let slices = sliceFn ? await sliceBuckets() : []; slices = slices.sort((a,b) => a.z - b.z); return { slices, points, zMin, zMax, zIndexes, zFlat }; @@ -261,12 +283,16 @@ * * @param {number} z */ - function sliceZ(z, points, options = {}) { + async function sliceZ(z, points, options = {}) { let { zMin, zMax, under, over, both } = options, + groupFn = dval(options.groupr, both ? null : sliceConnect), phash = {}, lines = [], p1, p2, p3; + // default to 'over' selection with 2 points on a line + if (!under && !both) over = true; + // iterate over matching buckets for this z offset for (let i = 0; i < points.length; ) { p1 = points[i++]; @@ -315,15 +341,10 @@ // de-dup and group lines lines = removeDuplicateLines(lines); - // connect lines into longest contiguous chains - if (options.group) { - return { - z, lines, - groups: connectLines(lines, z, { debug: options.debug }) - }; - } else { - return { z, lines }; - } + let rval = { z, lines }; + if (groupFn) rval.groups = groupFn(lines, z, options); + + return rval; } /** @@ -336,8 +357,13 @@ * @param {number} [index] * @returns {Array} */ - function connectLines(input, z, opt = {}) { - let { debug } = opt; + function sliceConnect(input, z, opt = {}) { + let { debug, both } = opt; + + if (both) { + if (debug) console.log('unable to connect lines sliced with "both" option'); + return []; + } // map points to all other points they're connected to let pmap = {}, @@ -746,5 +772,6 @@ } base.slice = slice; + base.sliceZ = sliceZ; })(); diff --git a/src/main/mesh.js b/src/main/mesh.js index 58018194..3d8050a7 100644 --- a/src/main/mesh.js +++ b/src/main/mesh.js @@ -284,7 +284,7 @@ function space_init(data) { if (shiftKey) return api.tool.merge(); return api.tool.mirror(); case 'KeyA': - return api.tool.analyze(); + return shiftKey ? api.tool.analyze() : undefined; case 'KeyR': if (shiftKey) return api.tool.rebuild(); return api.tool.repair(); diff --git a/src/mesh/work.js b/src/mesh/work.js index d8c3e615..888d5dd0 100644 --- a/src/mesh/work.js +++ b/src/mesh/work.js @@ -304,7 +304,7 @@ let model = { autoDim: true, flat: true, both: true, - // debug: true, + debug: true, minstep: 0.25, }).then(output => { let { points, slices } = output; @@ -319,7 +319,7 @@ let model = { return base.slice(points, { autoDim: true, both: true, - // debug: true, + debug: true, minstep: 0.25, }).then(output => { let { points, slices } = output;