2020-06-03 22:39:30 -04:00
|
|
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
|
|
|
|
if (self.kiri.Slice) return;
|
|
|
|
|
|
2020-06-03 22:39:30 -04:00
|
|
|
const KIRI = self.kiri,
|
|
|
|
|
PRO = Slice.prototype,
|
2017-04-18 17:09:33 -04:00
|
|
|
BASE = self.base,
|
|
|
|
|
UTIL = BASE.util,
|
|
|
|
|
POLY = BASE.polygons,
|
2020-11-07 14:55:15 -05:00
|
|
|
NOKEY = BASE.key.NONE;
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
KIRI.Top = Top;
|
|
|
|
|
KIRI.newTop = newTop;
|
|
|
|
|
KIRI.Slice = Slice;
|
|
|
|
|
KIRI.newSlice = newSlice;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Object encapsulates a z-slice from an object. This code is shared by the
|
|
|
|
|
* client and the worker thread. As such, the view layers are ignored in the
|
|
|
|
|
* worker code paths.
|
|
|
|
|
*
|
|
|
|
|
* @param {number} z offset from ground
|
|
|
|
|
* @param {THREE.Group} [view] optional view parent object for layers
|
|
|
|
|
* @constructor
|
|
|
|
|
*/
|
|
|
|
|
function Slice(z, view) {
|
|
|
|
|
this.z = z; // z-index
|
|
|
|
|
this.index = 0; // slice index
|
2020-11-07 14:55:15 -05:00
|
|
|
this.lines = null; // slice raw
|
|
|
|
|
this.groups = null; // grouped lines
|
2017-04-18 17:09:33 -04:00
|
|
|
this.up = null; // slice above (linked list)
|
|
|
|
|
this.down = null; // slice below (linked list)
|
|
|
|
|
this.tops = []; // array of Top objects
|
|
|
|
|
this.view = view; // for rendering this slice
|
2020-02-11 09:27:34 -05:00
|
|
|
this.finger = null; // cached fingerprint
|
2020-11-06 21:43:28 -05:00
|
|
|
this.render = null; // will replace most of the layer output data
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Represents a top-level (outer) polygon in a slice. Slices may contain
|
|
|
|
|
* multiple tops each with nested structures. Top objects contain cached
|
|
|
|
|
* and computed objects for quick access for rendering and dependent computations.
|
|
|
|
|
*
|
|
|
|
|
* @param {Polygon} polygon
|
|
|
|
|
* @constructor
|
|
|
|
|
*/
|
|
|
|
|
function Top(polygon) {
|
|
|
|
|
this.poly = polygon; // outline poly
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-07 14:55:15 -05:00
|
|
|
Top.prototype.clone = function(deep) {
|
|
|
|
|
let top = new Top(this.poly.clone(deep));
|
|
|
|
|
return top;
|
|
|
|
|
};
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
/**
|
|
|
|
|
* return innermost traces under a given top. for FDM, this represents
|
2020-11-07 14:55:15 -05:00
|
|
|
* the outline shell that the fill touches. used by Print, Laser
|
2017-04-18 17:09:33 -04:00
|
|
|
*/
|
|
|
|
|
Top.prototype.innerTraces = function() {
|
2020-04-13 19:28:17 -04:00
|
|
|
let traces = this.traces,
|
2017-04-18 17:09:33 -04:00
|
|
|
array = [];
|
|
|
|
|
if (traces) traces.forEach(function(p) {
|
|
|
|
|
if (p.inner) array.appendAll(p.inner);
|
|
|
|
|
});
|
|
|
|
|
return array;
|
|
|
|
|
};
|
|
|
|
|
|
2017-12-06 19:01:08 -05:00
|
|
|
/**
|
2020-11-07 14:55:15 -05:00
|
|
|
* Appends all outermost trace polygons into a given array
|
|
|
|
|
* and returns it. used by Print
|
2017-12-06 19:01:08 -05:00
|
|
|
*
|
|
|
|
|
* @param {Polygon[]} out array to populate
|
|
|
|
|
* @returns {Polygon[]} array of top polygons
|
|
|
|
|
*/
|
|
|
|
|
Top.prototype.gatherOuter = function(out) {
|
|
|
|
|
this.traces.forEach(function(trace) {
|
|
|
|
|
if (trace.depth === 0) out.append(trace);
|
|
|
|
|
});
|
|
|
|
|
return out;
|
|
|
|
|
};
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
/** ******************************************************************
|
|
|
|
|
* Slice Prototype Functions
|
|
|
|
|
******************************************************************* */
|
|
|
|
|
|
2020-11-06 21:43:28 -05:00
|
|
|
/**
|
|
|
|
|
* return Render object for this slice. creates it if necessary.
|
|
|
|
|
*/
|
|
|
|
|
PRO.output = function() {
|
|
|
|
|
if (this.render) return this.render;
|
|
|
|
|
return this.render = new KIRI.Render();
|
|
|
|
|
};
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
/**
|
|
|
|
|
* returns a cloned slice the option of a deep clone on the top polys
|
|
|
|
|
*/
|
2017-10-28 13:30:08 -04:00
|
|
|
PRO.clone = function(deep) {
|
2020-11-07 14:55:15 -05:00
|
|
|
const from = this, slice = newSlice(from.z, from.view);
|
2017-04-18 17:09:33 -04:00
|
|
|
from.tops.forEach(function(top) {
|
|
|
|
|
slice.addTop(top.poly.clone(deep));
|
|
|
|
|
});
|
|
|
|
|
return slice;
|
|
|
|
|
};
|
|
|
|
|
|
2020-11-07 14:55:15 -05:00
|
|
|
PRO.topPolys = function() {
|
|
|
|
|
return this.tops.map(top => top.poly);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// FDM / SLA only
|
|
|
|
|
PRO.topInners = function() {
|
|
|
|
|
return this.tops.map(top => top.last).flat().filter(poly => poly);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// FDM / SLA only
|
|
|
|
|
PRO.topFillOff = function() {
|
|
|
|
|
return this.tops.map(top => top.fill_off).flat().filter(poly => poly);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// FDM only
|
|
|
|
|
PRO.topFill = function() {
|
|
|
|
|
return this.tops.map(top => top.fill_lines).flat().filter(poly => poly);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// FDM only
|
|
|
|
|
PRO.topShells = function() {
|
|
|
|
|
return this.tops.map(top => top.shells).flat().filter(poly => poly);
|
|
|
|
|
};
|
|
|
|
|
|
2020-02-11 09:27:34 -05:00
|
|
|
/**
|
|
|
|
|
* 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;
|
|
|
|
|
}
|
2020-11-07 14:55:15 -05:00
|
|
|
return this.finger = POLY.fingerprint(this.topPolys());
|
2020-02-11 09:27:34 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* returns true if the layers' fingerprints are the same
|
|
|
|
|
*/
|
|
|
|
|
PRO.fingerprintSame = function(slice) {
|
2020-11-07 14:55:15 -05:00
|
|
|
return slice ? POLY.fingerprintCompare(this.fingerprint(), slice.fingerprint()) : false;
|
2017-04-18 17:09:33 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add a polygon to a slice creating a new top when necessary.
|
|
|
|
|
*
|
|
|
|
|
* @param {Polygon} poly to merge into a top
|
|
|
|
|
*/
|
2020-11-07 14:55:15 -05:00
|
|
|
// PRO.mergeTop = function(poly) {
|
|
|
|
|
// let slice = this,
|
|
|
|
|
// tops = slice.tops,
|
|
|
|
|
// union, i;
|
|
|
|
|
// for (i=0; i<tops.length; i++) {
|
|
|
|
|
// if (union = poly.union(tops[i].poly)) {
|
|
|
|
|
// tops[i].poly = union;
|
|
|
|
|
// return tops[i];
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// return slice.addTop(poly);
|
|
|
|
|
// };
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2020-11-03 14:49:01 -05:00
|
|
|
PRO.addTops = function(polys) {
|
|
|
|
|
polys.forEach(p => {
|
|
|
|
|
this.addTop(p);
|
|
|
|
|
});
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
/**
|
|
|
|
|
* Create a new top object given a polygon
|
|
|
|
|
*
|
|
|
|
|
* @param {Polygon} poly to add
|
|
|
|
|
*/
|
2017-10-28 13:30:08 -04:00
|
|
|
PRO.addTop = function(poly) {
|
2020-04-13 19:28:17 -04:00
|
|
|
let top = new Top(poly);
|
2017-04-18 17:09:33 -04:00
|
|
|
this.tops.push(top);
|
|
|
|
|
return top;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
2017-12-06 18:53:42 -05:00
|
|
|
* Returns all top polygons as an array
|
2017-04-18 17:09:33 -04:00
|
|
|
*
|
|
|
|
|
* @param {Polygon[]} out array to populate
|
|
|
|
|
* @returns {Polygon[]} array of top polygons
|
|
|
|
|
*/
|
2020-11-07 14:55:15 -05:00
|
|
|
// PRO.gatherTopPolys = function(out) {
|
|
|
|
|
// this.tops.forEach(function(top) {
|
|
|
|
|
// out.push(top.poly);
|
|
|
|
|
// });
|
|
|
|
|
// return out;
|
|
|
|
|
// };
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Appends all inner trace inner polygons (holes)
|
|
|
|
|
* into a given array and returns it
|
|
|
|
|
*
|
|
|
|
|
* @param {Polygon[]} out array to populate
|
|
|
|
|
* @returns {Polygon[]} array of top polygons
|
|
|
|
|
*/
|
2020-11-07 14:55:15 -05:00
|
|
|
// PRO.gatherTopPolyInners = function(out) {
|
|
|
|
|
// this.tops.forEach(function(top) {
|
|
|
|
|
// if (top.poly.inner) out.appendAll(top.poly.inner);
|
|
|
|
|
// });
|
|
|
|
|
// return out;
|
|
|
|
|
// };
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Appends all trace polygons into a given array and returns it
|
|
|
|
|
*
|
|
|
|
|
* @param {Polygon[]} out array to populate
|
|
|
|
|
* @returns {Polygon[]} array of top polygons
|
|
|
|
|
*/
|
2020-11-07 14:55:15 -05:00
|
|
|
// PRO.gatherTraces = function(out) {
|
|
|
|
|
// this.tops.forEach(function(top) {
|
|
|
|
|
// out.appendAll(top.traces);
|
|
|
|
|
// });
|
|
|
|
|
// return out;
|
|
|
|
|
// };
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Appends all innermost trace polygons into a given array and returns it
|
|
|
|
|
*
|
|
|
|
|
* @param {Polygon[]} out array to populate
|
|
|
|
|
* @returns {Polygon[]} array of top polygons
|
|
|
|
|
*/
|
2020-11-07 14:55:15 -05:00
|
|
|
// PRO.gatherInner = function(out) {
|
|
|
|
|
// this.tops.forEach(function(top) {
|
|
|
|
|
// out.appendAll(top.inner);
|
|
|
|
|
// });
|
|
|
|
|
// return out;
|
|
|
|
|
// };
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Appends all solid area polygons into a given array and returns it
|
|
|
|
|
*
|
|
|
|
|
* @param {Polygon[]} out array to populate
|
|
|
|
|
* @returns {Polygon[]} array of top polygons
|
|
|
|
|
*/
|
2020-11-07 14:55:15 -05:00
|
|
|
// PRO.gatherSolids = function(out) {
|
|
|
|
|
// this.tops.forEach(function(top) {
|
|
|
|
|
// out.appendAll(top.solids);
|
|
|
|
|
// });
|
|
|
|
|
// return out;
|
|
|
|
|
// };
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* return all fill lines. includes points for solid layers,
|
|
|
|
|
* solid polygon regions and support line polygons.
|
|
|
|
|
*
|
|
|
|
|
* @param {Point[]} [lines] array to append to
|
|
|
|
|
*/
|
2020-11-07 14:55:15 -05:00
|
|
|
// PRO.gatherFillLines = function(lines) {
|
|
|
|
|
// this.tops.forEach(function(top) {
|
|
|
|
|
// if (top.fill_lines) lines.appendAll(top.fill_lines);
|
|
|
|
|
// });
|
|
|
|
|
// return lines;
|
|
|
|
|
// };
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
function newTop(poly) {
|
|
|
|
|
return new Top(poly);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {number} z
|
|
|
|
|
* @param {THREE.Group} view
|
|
|
|
|
* @returns {Slice}
|
|
|
|
|
*/
|
|
|
|
|
function newSlice(z, view) {
|
|
|
|
|
return new Slice(z, view);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
})();
|