add array grouping and walk order. add new thin fill output method

This commit is contained in:
Stewart Allen 2021-12-30 17:35:10 -05:00
commit 5e6c4b91aa
4 changed files with 81 additions and 2 deletions

View file

@ -180,6 +180,20 @@
return this.filter(v => isNaN(v)).length > 0; return this.filter(v => isNaN(v)).length > 0;
}; };
// turn array into arrays of specified size
AP.group = function(size) {
let na = new Array(Math.ceil(this.length / size));
let nai = 0;
for (let i=0; i<this.length; i += size) {
let grp = new Array(size);
for (let j=0; j<size; j++) {
grp[j] = this[i+j];
}
na[nai++] = grp;
}
return na;
};
// wrap a function and unroll the first parameter into // wrap a function and unroll the first parameter into
// successive function calls if it is an array // successive function calls if it is an array
Array.handle = function(fn) { Array.handle = function(fn) {

View file

@ -428,6 +428,39 @@
return diff; return diff;
} }
// order array of elements using next closest element comparator
// used for things like next-closest point walks (fdm thin fill)
// in future, replace poly2poly and similar with this
function orderClosest(array, fn, from) {
if (!array.length) {
return array;
}
let out = new Array(array.length);
let outi = 0;
let root = 0;
if (!from) {
from = array[root++];
out[outi++] = from;
}
for (;;) {
let best, best_i, best_dist = Infinity;
for (let i=root; i<array.length; i++) {
let el = array[i];
if (!el) continue;
let dist = fn(from, el);
if (dist < best_dist) {
best_dist = dist;
best_i = i;
best = el;
}
}
if (!best) break;
array[best_i] = undefined;
from = out[outi++] = best;
}
return out;
}
/** ****************************************************************** /** ******************************************************************
* Connect to base * Connect to base
******************************************************************* */ ******************************************************************* */
@ -530,6 +563,7 @@
intersect, intersect,
determinant, determinant,
numOrDefault, numOrDefault,
orderClosest,
zInPlane, zInPlane,
comma: (v) => { comma: (v) => {
if (!v) return v; if (!v) return v;

View file

@ -834,6 +834,37 @@
}); });
} }
function outputThin(lines) {
let points = lines.group(2).map(grp => {
let [ p1, p2 ] = grp;
return newPoint(
(p1.x + p2.x) / 2,
(p1.y + p2.y) / 2,
(p1.z + p2.z) / 2
)
});
let order = UTIL.orderClosest(points, (p1, p2) => p1.distTo2D(p2));
if (order.length === 0) {
return;
}
let first = points[0];
let last = first;
addOutput(preout, first, 0, moveSpeed, extruder);
for (let p of order) {
let dist = last ? last.distTo2D(p) : 0;
if (dist > thinWall) {
retract();
addOutput(preout, p, 0, moveSpeed, extruder);
}
addOutput(preout, p, 1, fillSpeed, extruder);
last = p;
}
// close a circle
if (last && last.distTo2D(first) <= thinWall) {
addOutput(preout, first, 1, fillSpeed, extruder);
}
}
function outputFills(lines, opt = {}) { function outputFills(lines, opt = {}) {
if (!lines || lines.length === 0) { if (!lines || lines.length === 0) {
return; return;
@ -1078,7 +1109,7 @@
setType('int'); setType('int');
// output thin fill // output thin fill
outputFills(next.thin_fill, {near: true}); outputThin(next.thin_fill);
// then output solid and sparse fill // then output solid and sparse fill
outputFills(next.fill_lines, {flow: solidWidth}); outputFills(next.fill_lines, {flow: solidWidth});

View file

@ -189,7 +189,7 @@
} else { } else {
// frop top object passed back by slicePost() // frop top object passed back by slicePost()
let top = new Top(poly.poly); let top = new Top(poly.poly);
top.thin_fill = poly.thin_fill.map(p => BASE.newPoint(p.x,p.y,p.z)); top.thin_fill = poly.thin_fill ? poly.thin_fill.map(p => BASE.newPoint(p.x,p.y,p.z)) : undefined;
top.fill_lines = poly.fill_lines; top.fill_lines = poly.fill_lines;
top.fill_off = poly.fill_off; top.fill_off = poly.fill_off;
top.last = poly.last; top.last = poly.last;