move fingerprinting into polygons utility class
This commit is contained in:
parent
6c0d804f8c
commit
674bb48689
6 changed files with 98 additions and 59 deletions
|
|
@ -45,6 +45,7 @@ var gs_base_polygon = exports;
|
|||
this.length = 0; // number of points
|
||||
this.points = []; // ordered array of points
|
||||
this.area2 = 0.0; // computed as 2x area (sign = direction)
|
||||
this.perim = 0.0; // for caching the result
|
||||
this.bounds = new Bounds();
|
||||
this.inner = null; // array of enclosed polygons (if any)
|
||||
this.parent = null; // enclosing parent polygon
|
||||
|
|
@ -799,13 +800,17 @@ var gs_base_polygon = exports;
|
|||
* @returns {number} perimeter length (sum of all segment lengths)
|
||||
*/
|
||||
PRO.perimeter = function() {
|
||||
if (this.perim !== 0.0) {
|
||||
return this.perim;
|
||||
}
|
||||
|
||||
var len = 0.0;
|
||||
|
||||
this.forEachSegment(function(prev,next) {
|
||||
len += SQRT(prev.distToSq2D(next));
|
||||
}, this.open);
|
||||
|
||||
return len;
|
||||
return this.perim = len;
|
||||
};
|
||||
|
||||
PRO.perimeterDeep = function() {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,9 @@ var gs_base_polygons = exports;
|
|||
toClipper : toClipper,
|
||||
fromClipperNode : fromClipperNode,
|
||||
fromClipperTree : fromClipperTree,
|
||||
cleanClipperTree : cleanClipperTree
|
||||
cleanClipperTree : cleanClipperTree,
|
||||
fingerprintCompare: fingerprintCompare,
|
||||
fingerprint: fingerprint
|
||||
};
|
||||
|
||||
/** ******************************************************************
|
||||
|
|
@ -803,4 +805,36 @@ var gs_base_polygons = exports;
|
|||
return points;
|
||||
}
|
||||
|
||||
function fingerprint(polys) {
|
||||
let finger = [];
|
||||
flatten(polys).sort((a,b) => {
|
||||
return a.area() > b.area();
|
||||
}).forEach(p => {
|
||||
finger.push(p.area());
|
||||
finger.push(p.perimeter());
|
||||
});
|
||||
return finger;
|
||||
}
|
||||
|
||||
function fingerprintCompare(a, b) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i=0; i<a.length; i += 2) {
|
||||
if (Math.abs(a[i] - b[i]) > 0.001) {
|
||||
return false;
|
||||
}
|
||||
if (Math.abs(a[i+1] - b[i+1]) > 0.0001) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ var gs_kiri_slice = exports;
|
|||
this.isSparseFill = false;
|
||||
this.camMode = null; // CAM mode
|
||||
this.layers = null;
|
||||
this.finger = null; // cached fingerprint
|
||||
|
||||
if (view) this.addLayers(view);
|
||||
}
|
||||
|
|
@ -135,6 +136,29 @@ var gs_kiri_slice = exports;
|
|||
return slice;
|
||||
};
|
||||
|
||||
/**
|
||||
* produces a fingerprint for a slice that should be the same for
|
||||
* layers that are identical. this happens in parts with unchanging
|
||||
* vertical wall regions. this allows us to eliminate expensive diffs
|
||||
* and infill computation when we detect the layers are the same.
|
||||
*/
|
||||
PRO.fingerprint = function() {
|
||||
if (this.finger) {
|
||||
return this.finger;
|
||||
}
|
||||
return this.finger = POLY.fingerprint(this.gatherTopPolys([]));
|
||||
};
|
||||
|
||||
/**
|
||||
* returns true if the layers' fingerprints are the same
|
||||
*/
|
||||
PRO.fingerprintSame = function(slice) {
|
||||
if (!slice) {
|
||||
return false;
|
||||
}
|
||||
return POLY.fingerprintCompare(this.fingerprint(), slice.fingerprint());
|
||||
};
|
||||
|
||||
/**
|
||||
* create layer objects for client-side rendering
|
||||
*
|
||||
|
|
@ -616,6 +640,7 @@ var gs_kiri_slice = exports;
|
|||
|
||||
var scope = this,
|
||||
tops = scope.tops,
|
||||
down = scope.down,
|
||||
clib = self.ClipperLib,
|
||||
ctyp = clib.ClipType,
|
||||
ptyp = clib.PolyType,
|
||||
|
|
@ -660,14 +685,28 @@ var gs_kiri_slice = exports;
|
|||
polys.appendAll(top.solids);
|
||||
});
|
||||
|
||||
scope.fingerprint = fingerprint(polys);
|
||||
if (scope.down && scope.down.fingerprint && samefinger(scope.down.fingerprint, scope.fingerprint)) {
|
||||
for (let i=0; i<tops.length; i++) {
|
||||
tops[i].fill_sparse = scope.down.tops[i].fill_sparse.map(poly => {
|
||||
return poly.clone().setZ(scope.z);
|
||||
});
|
||||
scope._fill_finger = POLY.fingerprint(polys);
|
||||
|
||||
let miss = false;
|
||||
// if the layer below has the same fingerprint, we may be able to clone its infill
|
||||
if (scope.fingerprintSame(down)) {
|
||||
// the fill fingerprint can slightly different because of solid projections
|
||||
if (down._fill_finger && POLY.fingerprintCompare(scope._fill_finger, down._fill_finger)) {
|
||||
for (let i=0; i<tops.length; i++) {
|
||||
// the layer below may not have infill computed if it's solid
|
||||
if (down.tops[i].fill_sparse) {
|
||||
tops[i].fill_sparse = down.tops[i].fill_sparse.map(poly => {
|
||||
return poly.clone().setZ(scope.z);
|
||||
});
|
||||
} else {
|
||||
miss = true;
|
||||
}
|
||||
}
|
||||
// if any of the fills as missing from below, re-compute
|
||||
if (!miss) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
clip.AddPaths(lines, ptyp.ptSubject, false);
|
||||
|
|
@ -706,47 +745,6 @@ var gs_kiri_slice = exports;
|
|||
layer.render();
|
||||
};
|
||||
|
||||
function fingerprint(polys) {
|
||||
let out = [];
|
||||
polys.sort((a,b) => {
|
||||
return a.area() > b.area();
|
||||
}).forEach(p => {
|
||||
out.push(p.area());
|
||||
out.push(p.perimeter());
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
function samefinger(a, b) {
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i=0; i<a.length; i += 2) {
|
||||
if (Math.abs(a[i] - b[i]) > 0.001) {
|
||||
return false;
|
||||
}
|
||||
if (Math.abs(a[i+1] - b[i+1]) > 0.0001) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function samesame(a, b) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
let fingerA = fingerprint(a),
|
||||
fingerB = fingerprint(b);
|
||||
return samefinger(fingerA, fingerB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find difference between fill inset poly on two adjacent layers.
|
||||
* Used to calculate bridges, flats and then solid projections.
|
||||
|
|
@ -766,7 +764,7 @@ var gs_kiri_slice = exports;
|
|||
flats = [];
|
||||
|
||||
// skip diffing layers that are identical
|
||||
if (samesame(topInner, bottomInner)) {
|
||||
if (this.fingerprintSame(bottom)) {
|
||||
top.bridges = bridges;
|
||||
bottom.flats = flats;
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
var exports = {
|
||||
COPYRIGHT:"Copyright (C) 2014-2019 Stewart Allen <sa@grid.space> - All Rights Reserved",
|
||||
LICENSE:"See the license.md file included with the source distribution",
|
||||
VERSION:"1.5.8"
|
||||
VERSION:"1.5.9"
|
||||
};
|
||||
if (!module) var module = {};
|
||||
module.exports = exports;
|
||||
|
|
|
|||
6
notes.md
6
notes.md
|
|
@ -15,6 +15,7 @@
|
|||
# FDM todo
|
||||
|
||||
* fingerprint layer once and re-use for infill and layer diffs
|
||||
* disable infill fingerprinting for gyroids
|
||||
* first layer segment large flat areas for better fill reliability
|
||||
* adaptive column to compensate for fine or layers that finish too quickly and melt
|
||||
* apply finish speed to exposed top and underside flat areas
|
||||
|
|
@ -38,7 +39,6 @@
|
|||
* optimize away topo generation (for z hop/move) when part is flat
|
||||
* add imperial / metric units switch in (future) global config options
|
||||
* add option to spiral in vs out (optimal tool life) vs mixed (optimal path)
|
||||
* pocket order should consider distance as well as size
|
||||
* ease-in and ease-out especially on tab cut-out start/stop
|
||||
* import options: unify bodies.
|
||||
* milling order option: by operation or by part
|
||||
|
|
@ -47,16 +47,14 @@
|
|||
* improve 'clockwise' setting to take into account spindle direction, etc
|
||||
* linear finishing cutting out tabs
|
||||
* linear finishing going back to z top too often
|
||||
* fix ease down and re-enable
|
||||
* fix ease down and re-enable (need failure case)
|
||||
* warn when part > stock or cuts go outside bed
|
||||
* option to skip milling holes that would be drilled
|
||||
* sender speed control slider (0%-200%) ?
|
||||
* add M03 tool feedrate support (https://forum.grid.space/index.php?p=/discussion/14/s-parameter#latest)
|
||||
* fails in pancaking (clone) when there are no sliced layers (like z bottom too high)
|
||||
* crossing open space check point is outside camshell before returning max z
|
||||
* compensate for leave-stock in outside roughing (w/ tabs)
|
||||
* fix zooming, workspace thickness for larger workspaces
|
||||
* only show toolchange alert/pause after the first M6
|
||||
* raise z by leave-stock in roughing? if so, see next
|
||||
* if (raise z) above, add clear-flats to finishing
|
||||
* revisit tabs - just cut polys instead
|
||||
|
|
|
|||
|
|
@ -14,7 +14,12 @@
|
|||
<li><button onclick="kiri.api.setMode('LASER')">LASER</button> : DXG / SVG cut paths
|
||||
|
||||
<p>
|
||||
<b>File Load and Import</b>
|
||||
<b>Learn More</b>
|
||||
<li>Watch <a target="_tutor" href="https://www.youtube.com/playlist?list=PLRoVgyRoWZpumQIKWm7oldx3bjDivqP24">a tutorial</a> on YouTube
|
||||
<li>Check out the <a target="_fb" href="https://www.facebook.com/groups/kirimoto">user group</a> on Facebook
|
||||
|
||||
<p>
|
||||
<b>File Load & Import</b>
|
||||
|
||||
<li>Drag and drop an <a href="https://en.wikipedia.org/wiki/STL_(file_format)" target="_stl">STL</a> onto the grid
|
||||
<li>Or load with Function [Import]
|
||||
|
|
@ -22,8 +27,7 @@
|
|||
|
||||
<p>
|
||||
<b>Start Working</b>
|
||||
<li>Consider <a target="_tutor" href="https://www.youtube.com/playlist?list=PLRoVgyRoWZpumQIKWm7oldx3bjDivqP24">watching a tutorial</a>
|
||||
<li>Select device mode (FDM, CAM, Laser)
|
||||
<li>Select device mode: FDM, CAM, Laser
|
||||
<li>Select device profile under Devices
|
||||
<li>Set slicing parameters in right menu
|
||||
<li>Test slicing settings with Function [Slice]
|
||||
|
|
|
|||
Loading…
Reference in a new issue