change fingerprinting algorithm

This commit is contained in:
Stewart Allen 2021-07-10 21:19:56 -04:00
commit aeb8d9512a
6 changed files with 79 additions and 20 deletions

View file

@ -58,6 +58,17 @@
UTIL.isCloseTo(this.maxy, bounds.maxy, margin); UTIL.isCloseTo(this.maxy, bounds.maxy, margin);
}; };
/**
* @returns {Number} absolute delta in x,y coordinate space
*/
PRO.delta = function(bounds) {
return
Math.abs(this.minx - bounds.minx) +
Math.abs(this.miny - bounds.miny) +
Math.abs(this.maxx - bounds.maxx) +
Math.abs(this.maxy - bounds.maxy);
};
/** /**
* @param {Bounds} b * @param {Bounds} b
*/ */

View file

@ -476,7 +476,7 @@
const pa = this.points, const pa = this.points,
pln = pa.length, pln = pa.length,
open = this.open, open = this.open,
newp = newPolygon(), newp = newPolygon().copyZ(this.z),
min = dist || BASE.config.precision_merge; min = dist || BASE.config.precision_merge;
let lo; let lo;
newp.push(lo = pa[0]); newp.push(lo = pa[0]);
@ -519,7 +519,7 @@
redo |= ang[0] > 90; redo |= ang[0] > 90;
} }
if (redo) { if (redo) {
const newp = newPolygon(); const newp = newPolygon().copyZ(this.z);
// newp.debug = this.debug = true; // newp.debug = this.debug = true;
newp.open = open; newp.open = open;
for (let i=0; i<pln; i++) { for (let i=0; i<pln; i++) {
@ -803,7 +803,7 @@
* @returns {Polygon} * @returns {Polygon}
*/ */
PRO.clone = function(deep) { PRO.clone = function(deep) {
let np = newPolygon(), let np = newPolygon().copyZ(this.z),
ln = this.length, ln = this.length,
i = 0; i = 0;
@ -820,6 +820,25 @@
return np; return np;
}; };
// special shallow for-render-or-read-only cloning
PRO.cloneZ = function(z, stop) {
let p = newPolygon();
p.z = z;
p.open = this.open;
p.points = this.points;
if (this.inner) {
p.inner = this.inner.map(p => p.cloneZ(z, true));
}
return p;
};
PRO.copyZ = function(z) {
if (z !== undefined) {
this.z = z;
}
return this;
};
/** /**
* set all points' z value * set all points' z value
* *
@ -839,7 +858,7 @@
* @returns {number} z value of first point * @returns {number} z value of first point
*/ */
PRO.getZ = function(i) { PRO.getZ = function(i) {
return this.points[i || 0].z; return this.z !== undefined ? this.z : this.points[i || 0].z;
}; };
/** /**

View file

@ -871,37 +871,62 @@
flatten(polys).sort((a,b) => { flatten(polys).sort((a,b) => {
return a.area() > b.area(); return a.area() > b.area();
}).forEach(p => { }).forEach(p => {
finger.push(p.area()); // finger.push(p.area());
finger.push(p.perimeter()); // finger.push(p.perimeter());
finger.push(p.bounds); // finger.push(p.bounds);
finger.push({
c: p.circularityDeep(),
p: p.perimeterDeep(),
b: p.bounds
});
}); });
return finger; return finger;
} }
// compare fingerprint arrays
function fingerprintCompare(a, b) { function fingerprintCompare(a, b) {
// true if array is the same object
if (a === b) { if (a === b) {
return true; return true;
} }
// fail on missing array
if (!a || !b) { if (!a || !b) {
return false; return false;
} }
// require identical length arrays
if (a.length !== b.length) { if (a.length !== b.length) {
return false; return false;
} }
for (let i=0; i<a.length; i += 3) { for (let i=0; i<a.length; i++) {
if (Math.abs(a[i] - b[i]) > 0.001) { let ra = a[i];
let rb = b[i];
// test circularity
if (Math.abs(ra.c - rb.c) > 0.001) {
return false; return false;
} }
if (Math.abs(a[i+1] - b[i+1]) > 0.0001) { // test perimeter
if (Math.abs(ra.p - rb.p) > 0.001) {
return false; return false;
} }
if (Math.abs(a[i+2].centerx() - b[i+2].centerx()) > 0.0001) { // test bounds
return false; if (ra.b.delta(rb.b) > 0.001) {
}
if (Math.abs(a[i+2].centery() - b[i+2].centery()) > 0.0001) {
return false; return false;
} }
} }
// for (let i=0; i<a.length; i += 3) {
// if (Math.abs(a[i] - b[i]) > 0.001) {
// return false;
// }
// if (Math.abs(a[i+1] - b[i+1]) > 0.0001) {
// return false;
// }
// if (Math.abs(a[i+2].centerx() - b[i+2].centerx()) > 0.0001) {
// return false;
// }
// if (Math.abs(a[i+2].centery() - b[i+2].centery()) > 0.0001) {
// return false;
// }
// }
return true; return true;
} }

View file

@ -257,7 +257,7 @@
return top; return top;
}); });
function encodePointArray(points, state) { function encodePointArray(points, state, z) {
if (!points) return null; if (!points) return null;
let array = codec.allocFloat32Array(points.length * 3), let array = codec.allocFloat32Array(points.length * 3),
@ -280,7 +280,7 @@
} }
array[pos++] = point.x; array[pos++] = point.x;
array[pos++] = point.y; array[pos++] = point.y;
array[pos++] = point.z; array[pos++] = z !== undefined ? z : point.z;
}); });
if (zeroOut && state.zeros) { if (zeroOut && state.zeros) {
@ -314,11 +314,10 @@
} }
state.poly[this.id] = this; state.poly[this.id] = this;
return { return {
type: 'poly', type: 'poly',
id: this.id, id: this.id,
array: encodePointArray(this.points, state), array: encodePointArray(this.points, state, this.z),
inner: encode(this.inner, state), inner: encode(this.inner, state),
parent: encode(this.parent, state), parent: encode(this.parent, state),
depth: this.depth, depth: this.depth,

View file

@ -85,6 +85,9 @@
} }
addPolys(polys, options) { addPolys(polys, options) {
if (polys.length === 0) {
return this;
}
if (options && options.clean) { if (options && options.clean) {
polys = polys.map(p => p.clean(true)); polys = polys.map(p => p.clean(true));
} }

View file

@ -600,7 +600,7 @@
output output
.setLayer("sparse fill", COLOR.infill) .setLayer("sparse fill", COLOR.infill)
.addPolys(top.fill_sparse || [], vopt({ offset, height, outline: true })) .addPolys(top.fill_sparse || [], vopt({ offset, height, outline: true, trace:true }))
if (top.thin_fill) output if (top.thin_fill) output
.setLayer("thin fill", COLOR.fill) .setLayer("thin fill", COLOR.fill)
@ -866,7 +866,7 @@
cache = !(options.cache === false), cache = !(options.cache === false),
type = options.type || 'hex'; type = options.type || 'hex';
if (slice.tops.length === 0 || density === 0.0 || slice.isSolidLayer) { if (slice.tops.length === 0 || density === 0.0 || slice.isSolidLayer || slice.index < 0) {
slice.isSparseFill = false; slice.isSparseFill = false;
return; return;
} }
@ -943,9 +943,11 @@
if (skippable && slice.fingerprintSame(down)) { if (skippable && slice.fingerprintSame(down)) {
// the fill fingerprint can slightly different because of solid projections // the fill fingerprint can slightly different because of solid projections
if (down._fill_finger && POLY.fingerprintCompare(slice._fill_finger, down._fill_finger)) { if (down._fill_finger && POLY.fingerprintCompare(slice._fill_finger, down._fill_finger)) {
// console.log({fill_clone: down.index});
for (let i=0; i<tops.length; i++) { for (let i=0; i<tops.length; i++) {
// the layer below may not have infill computed if it's solid // the layer below may not have infill computed if it's solid
if (down.tops[i].fill_sparse) { if (down.tops[i].fill_sparse) {
// tops[i].fill_sparse = down.tops[i].fill_sparse.map(p => p.cloneZ(slice.z));
tops[i].fill_sparse = down.tops[i].fill_sparse.map(poly => { tops[i].fill_sparse = down.tops[i].fill_sparse.map(poly => {
return poly.clone().setZ(slice.z); return poly.clone().setZ(slice.z);
}); });