work on taper bits and linear finishing performance

This commit is contained in:
Stewart Allen 2020-03-11 00:53:19 -04:00
commit 2290a945ae

View file

@ -2,7 +2,7 @@
"use strict"; "use strict";
var gs_kiri_cam = exports; let gs_kiri_cam = exports;
(function() { (function() {
@ -10,7 +10,7 @@ var gs_kiri_cam = exports;
if (!self.kiri.driver) self.kiri.driver = { }; if (!self.kiri.driver) self.kiri.driver = { };
if (self.kiri.driver.CAM) return; if (self.kiri.driver.CAM) return;
var KIRI = self.kiri, let KIRI = self.kiri,
BASE = self.base, BASE = self.base,
UTIL = BASE.util, UTIL = BASE.util,
POLY = BASE.polygons, POLY = BASE.polygons,
@ -49,34 +49,41 @@ var gs_kiri_cam = exports;
time = UTIL.time; time = UTIL.time;
function getToolById(settings, id) { function getToolById(settings, id) {
for (var i=0, t=settings.tools; i<t.length; i++) { for (let i=0, t=settings.tools; i<t.length; i++) {
if (t[i].id === id) return t[i]; if (t[i].id === id) return t[i];
} }
return null; return null;
}; };
function getToolDiameter(settings, id) { function getToolDiameter(settings, id) {
var tool = getToolById(settings, id); let tool = getToolById(settings, id);
if (!tool) return 0; if (!tool) return 0;
return (tool.metric ? 1 : 25.4) * tool.flute_diam; return (tool.metric ? 1 : 25.4) * tool.flute_diam;
}; };
function getToolTipDiameter(settings, id) {
let tool = getToolById(settings, id);
if (!tool) return 0;
return (tool.metric ? 1 : 25.4) * tool.taper_tip;
};
function getToolShaftDiameter(settings, id) { function getToolShaftDiameter(settings, id) {
var tool = getToolById(settings, id); let tool = getToolById(settings, id);
if (!tool) return 0; if (!tool) return 0;
return (tool.metric ? 1 : 25.4) * tool.shaft_diam; return (tool.metric ? 1 : 25.4) * tool.shaft_diam;
}; };
function getToolShaftOffset(settings, id) { function getToolShaftOffset(settings, id) {
var tool = getToolById(settings, id); let tool = getToolById(settings, id);
if (!tool) return 0; if (!tool) return 0;
return (tool.metric ? 1 : 25.4) * tool.flute_len; return (tool.metric ? 1 : 25.4) * tool.flute_len;
}; };
function createToolProfile(settings, id, topo) { function createToolProfile(settings, id, topo) {
// generate tool profile // generate tool profile
var tool = getToolById(settings, id), let tool = getToolById(settings, id),
ball = tool.type === "ballmill", ball = tool.type === "ballmill",
taper = tool.type === "tapermill",
shaft_diameter = getToolShaftDiameter(settings, id), shaft_diameter = getToolShaftDiameter(settings, id),
shaft_radius = shaft_diameter / 2, shaft_radius = shaft_diameter / 2,
shaft_pix_float = shaft_diameter / topo.resolution, shaft_pix_float = shaft_diameter / topo.resolution,
@ -86,31 +93,66 @@ var gs_kiri_cam = exports;
flute_diameter = getToolDiameter(settings, id), flute_diameter = getToolDiameter(settings, id),
flute_radius = flute_diameter / 2, flute_radius = flute_diameter / 2,
flute_pix_float = flute_diameter / topo.resolution, flute_pix_float = flute_diameter / topo.resolution,
flute_pix_int = Math.round(flute_pix_float), // flute_pix_int = Math.round(flute_pix_float),
flute_radius_pix_float = flute_pix_float / 2, flute_radius_pix_float = flute_pix_float / 2,
tip_diameter = getToolTipDiameter(settings, id),
tip_pix_float = tip_diameter / topo.resolution,
tip_radius_pix_float = tip_pix_float / 2,
tip_max_radius_offset = flute_radius_pix_float - tip_radius_pix_float,
profile_pix_iter = shaft_pix_int + (1 - shaft_pix_int % 2), profile_pix_iter = shaft_pix_int + (1 - shaft_pix_int % 2),
toolCenter = (shaft_pix_int - (shaft_pix_int % 2)) / 2, toolCenter = (shaft_pix_int - (shaft_pix_int % 2)) / 2,
toolOffset = [], toolOffset = [],
larger_shaft = shaft_diameter - flute_diameter > 0.001; larger_shaft = shaft_diameter - flute_diameter > 0.001;
// console.log({id:tool.id, diam:flute_diameter, pix:flute_pix_float, tocks:profile_pix_iter}); // console.log({
// tool: tool.name,
// rez: topo.resolution,
// diam: flute_diameter,
// pix: flute_pix_float.toFixed(2),
// rad: flute_radius_pix_float.toFixed(2),
// tocks: profile_pix_iter,
// shaft_offset,
// larger_shaft
// });
// for each pixel in tool profile, check inside radius let bounds = toolOffset.bounds = {
for (var x = 0; x < profile_pix_iter; x++) { minx: Infinity, maxx: -Infinity,
for (var y = 0; y < profile_pix_iter; y++) { miny: Infinity, maxy: -Infinity
var dx = x - toolCenter, };
// for each point in tool profile, check inside radius
for (let x = 0; x < profile_pix_iter; x++) {
// let dbl = [];
for (let y = 0; y < profile_pix_iter; y++) {
let dx = x - toolCenter,
dy = y - toolCenter, dy = y - toolCenter,
dist_from_center = Math.sqrt(dx * dx + dy * dy); dist_from_center = Math.sqrt(dx * dx + dy * dy),
nup;
if (dist_from_center <= flute_radius_pix_float) { if (dist_from_center <= flute_radius_pix_float) {
var z_offset = ball ? (1 - Math.cos((dist_from_center / flute_radius_pix_float) * HPI)) * -flute_radius : 0; // console.log({x,y,dx,dy,dist:dist_from_center,ln:dbl.length})
toolOffset.push([dx, dy, z_offset]); // flute offset points
} else if (larger_shaft && dist_from_center <= shaft_radius_pix_float) { let z_offset = 0;
toolOffset.push([dx, dy, -shaft_offset]); if (ball) {
z_offset = (1 - Math.cos((dist_from_center / flute_radius_pix_float) * HPI)) * -flute_radius;
} else if (taper && dist_from_center >= tip_radius_pix_float) {
z_offset = ((dist_from_center - tip_radius_pix_float) / tip_max_radius_offset) * -shaft_offset;
}
toolOffset.push(nup = [dx, dy, z_offset]);
} else if (shaft_offset && larger_shaft && dist_from_center <= shaft_radius_pix_float) {
// shaft offset points
toolOffset.push(nup = [dx, dy, -shaft_offset]);
} }
if (nup) {
bounds.minx = Math.min(bounds.minx, dx);
bounds.maxx = Math.max(bounds.maxx, dx);
bounds.miny = Math.min(bounds.miny, dx);
bounds.maxy = Math.max(bounds.maxy, dx);
}
// if (nup) dbl.push(toolOffset[toolOffset.length-1][2]);
} }
// console.log(dbl.length,dbl.map(v => Math.abs(v).toFixed(1)).join(','));
} }
// console.log(tool.name,toolOffset.length,toolOffset.bounds)
return toolOffset; return toolOffset;
}; };
@ -120,7 +162,7 @@ var gs_kiri_cam = exports;
*/ */
function getTopoZPathMax(widget, profile, x1, y1, x2, y2) { function getTopoZPathMax(widget, profile, x1, y1, x2, y2) {
var topo = widget.topo, let topo = widget.topo,
rez = topo.resolution, rez = topo.resolution,
bounds = widget.getBoundingBox(), bounds = widget.getBoundingBox(),
dx = x2-x1, dx = x2-x1,
@ -131,8 +173,11 @@ var gs_kiri_cam = exports;
iy = dy / mi, iy = dy / mi,
zmax = 0; zmax = 0;
// implement fast grid fingerprinting. if no z variance within
// the scan area (or min scan delta set from last point), then
// use the last computed zmax and carry on
while (mi-- > 0) { while (mi-- > 0) {
var tx1 = Math.round((x1 - bounds.min.x) / rez), let tx1 = Math.round((x1 - bounds.min.x) / rez),
ty1 = Math.round((y1 - bounds.min.y) / rez); ty1 = Math.round((y1 - bounds.min.y) / rez);
zmax = Math.max(zmax, getMaxTopoToolZ(topo, profile, tx1, ty1, true)); zmax = Math.max(zmax, getMaxTopoToolZ(topo, profile, tx1, ty1, true));
x1 += ix; x1 += ix;
@ -142,32 +187,61 @@ var gs_kiri_cam = exports;
return zmax; return zmax;
}; };
const lastTopo = {
lx:0,
ly:0,
lr:undefined
};
/** /**
* x,y are in topo grid int coordinates * x,y are in topo grid int coordinates
*/ */
function getMaxTopoToolZ(topo, profile, x, y, floormax) { function getMaxTopoToolZ(topo, profile, x, y, floormax) {
var tv, tx, ty, tz, gv, let tv, tx, ty, tz, gv, i = 0, mz = -1;
i = 0, mz = -1,
sx = topo.stepsx, sy = topo.stepsy, const sx = topo.stepsx, sy = topo.stepsy;
data = topo.data;
let {lx, ly, lr} = lastTopo;
let dx = x - lx;
let dy = y - ly;
while (i < profile.length) { while (i < profile.length) {
tv = profile[i++]; tv = profile[i++];
if (dx == -1 && tv[0] > 0) continue;
if (dx == 1 && tv[0] < 0) continue;
if (dy == -1 && tv[1] > 0) continue;
if (dy == 1 && tv[1] < 0) continue;
tx = tv[0] + x; tx = tv[0] + x;
ty = tv[1] + y; ty = tv[1] + y;
if (tx < 0 || tx >= sx || ty < 0 || ty >= sy) continue;
gv = data[tx * sy + ty]; // if outside max topo steps, skip
if (tx < 0 || tx >= sx || ty < 0 || ty >= sy) {
continue;
}
// lookup grid value @ tx, ty
gv = topo.data[tx * sy + ty];
// outside the topo
if (gv === undefined) { if (gv === undefined) {
continue; continue;
} }
// inside the topo but off the part
if (floormax && gv === 0) { if (floormax && gv === 0) {
return topo.bounds.max.z; // return topo.bounds.max.z;
gv = topo.bounds.max.z;
} }
// update the rest
tz = tv[2] + gv; tz = tv[2] + gv;
mz = Math.max(tz, mz); mz = Math.max(tz, mz);
} }
return mz >= 0.0 ? mz : topo.bounds.max.z; lastTopo.lx = x;
lastTopo.ly = y;
lastTopo.lr = mz >= 0.0 ? mz : topo.bounds.max.z;
return lastTopo.lr;
}; };
/** /**
@ -181,7 +255,7 @@ var gs_kiri_cam = exports;
* top down progressive union for CAM * top down progressive union for CAM
*/ */
function pancake(slices, onupdate) { function pancake(slices, onupdate) {
var union, tops, last; let union, tops, last;
slices.forEach(function(slice,index) { slices.forEach(function(slice,index) {
tops = slice.gatherTopPolys([]).clone(true); tops = slice.gatherTopPolys([]).clone(true);
@ -210,7 +284,7 @@ var gs_kiri_cam = exports;
* return slice closest to specified z * return slice closest to specified z
*/ */
function closestSliceToZ(slices, z) { function closestSliceToZ(slices, z) {
var selected = null, let selected = null,
distance = Infinity, distance = Infinity,
nextdist; nextdist;
slices.forEach(function(slice) { slices.forEach(function(slice) {
@ -227,7 +301,7 @@ var gs_kiri_cam = exports;
* select from pancaked layers * select from pancaked layers
*/ */
function selectSlices(slices, step, mode, output) { function selectSlices(slices, step, mode, output) {
var last, zlastout, emitted = []; let last, zlastout, emitted = [];
function emit(slice) { function emit(slice) {
// prevent double emit at end // prevent double emit at end
@ -235,7 +309,7 @@ var gs_kiri_cam = exports;
last = slice; last = slice;
if (slice.camMode) { if (slice.camMode) {
// clone to prevent double emit // clone to prevent double emit
var nuslice = newSlice(slice.z); let nuslice = newSlice(slice.z);
slice.tops.forEach(function(top) { slice.tops.forEach(function(top) {
nuslice.addTop(top.poly.clone(true)); nuslice.addTop(top.poly.clone(true));
}); });
@ -249,16 +323,16 @@ var gs_kiri_cam = exports;
// - find mandatory slices // - find mandatory slices
// - divide space between by step // - divide space between by step
// - select closes spaces for divisible gap // - select closes spaces for divisible gap
var forced = []; let forced = [];
slices.forEach(function(slice) { slices.forEach(function(slice) {
if (slice.hasFlats) forced.push(slice); if (slice.hasFlats) forced.push(slice);
}) })
var mid = []; let mid = [];
forced.forEachPair(function(s1, s2) { forced.forEachPair(function(s1, s2) {
// skip last to first pair // skip last to first pair
if (s2.z > s1.z) return; if (s2.z > s1.z) return;
var delta = Math.abs(s2.z - s1.z), let delta = Math.abs(s2.z - s1.z),
inc = delta / step, inc = delta / step,
nstep = step, nstep = step,
dec = inc - Math.floor(inc), dec = inc - Math.floor(inc),
@ -268,7 +342,7 @@ var gs_kiri_cam = exports;
// add another step if decimal too high // add another step if decimal too high
if (dec > slop) nstep = delta / Math.ceil(inc); if (dec > slop) nstep = delta / Math.ceil(inc);
// find closest slices in-between // find closest slices in-between
for (var zv = s1.z - nstep; zv >= s2.z + nstep/2; zv -= nstep) { for (let zv = s1.z - nstep; zv >= s2.z + nstep/2; zv -= nstep) {
mid.push(closestSliceToZ(slices, zv)); mid.push(closestSliceToZ(slices, zv));
} }
}, 1); }, 1);
@ -293,7 +367,7 @@ var gs_kiri_cam = exports;
* remove collinear points (todo) * remove collinear points (todo)
*/ */
function cleanupTopoSlice(slice, diameter, curvesOnly) { function cleanupTopoSlice(slice, diameter, curvesOnly) {
var poly = slice.tops[0].traces[0], let poly = slice.tops[0].traces[0],
nupoly = newPolygon().setOpen(), nupoly = newPolygon().setOpen(),
points = poly.points, points = poly.points,
start = 0, start = 0,
@ -328,7 +402,7 @@ var gs_kiri_cam = exports;
if (nupoly.length < 2) return false; if (nupoly.length < 2) return false;
// limit cleanup to curved features // limit cleanup to curved features
var traces = [], let traces = [],
trace = newPolygon().setOpen(); trace = newPolygon().setOpen();
slice.tops[0].traces = traces; slice.tops[0].traces = traces;
@ -337,7 +411,7 @@ var gs_kiri_cam = exports;
latent = null; latent = null;
for (i = 1; i < points.length; i++) { for (i = 1; i < points.length; i++) {
point = points[i]; point = points[i];
var use = curvesOnly ? let use = curvesOnly ?
(last.z != point.z && (last.x !== point.x || last.y !== point.y)) : (last.z != point.z && (last.x !== point.x || last.y !== point.y)) :
last.z && point.z; last.z && point.z;
if (use) { if (use) {
@ -373,7 +447,7 @@ var gs_kiri_cam = exports;
* @param {Function} onupdate * @param {Function} onupdate
*/ */
function generateTopoMap(widget, settings, ondone, onupdate) { function generateTopoMap(widget, settings, ondone, onupdate) {
var mesh = widget.mesh, let mesh = widget.mesh,
proc = settings.process, proc = settings.process,
outp = settings.process, outp = settings.process,
units = settings.controller.units === 'in' ? 25.4 : 1, units = settings.controller.units === 'in' ? 25.4 : 1,
@ -413,7 +487,7 @@ var gs_kiri_cam = exports;
} }
function topoSlicesDone(slices) { function topoSlicesDone(slices) {
var gridx = 0, let gridx = 0,
gridy, gridy,
gridi, // index gridi, // index
gridv, // value gridv, // value
@ -424,19 +498,19 @@ var gs_kiri_cam = exports;
x, y, tv, ltv; x, y, tv, ltv;
// for each Y slice, find z grid value (x/z swapped) // for each Y slice, find z grid value (x/z swapped)
for (var j=0; j<slices.length; j++) { for (let j=0; j<slices.length; j++) {
var slice = slices[j], let slice = slices[j],
lodata = data, lodata = data,
lines = slice.lines; lines = slice.lines;
gridy = 0; gridy = 0;
// slices have x/z swapped // slices have x/z swapped
x = slice.z - maxx; // x = slice.z - maxx;
for (y = miny; y <= maxy; y += resolution) { for (y = miny; y <= maxy; y += resolution) {
gridi = gridx * stepsy + gridy; gridi = gridx * stepsy + gridy;
gridv = lodata[gridi] || 0; gridv = lodata[gridi] || 0;
// strategy using raw lines (faster slice, but more lines) // strategy using raw lines (faster slice, but more lines)
for (var i=0; i<lines.length; i++) { for (let i=0; i<lines.length; i++) {
var line = lines[i], let line = lines[i],
p1 = line.p1, p1 = line.p1,
p2 = line.p2;//, p2 = line.p2;//,
if ( if (
@ -445,7 +519,7 @@ var gs_kiri_cam = exports;
((p1.y <= y && p2.y >= y) || // one endpoint left ((p1.y <= y && p2.y >= y) || // one endpoint left
(p2.y <= y && p1.y >= y)) // one endpoint right (p2.y <= y && p1.y >= y)) // one endpoint right
) { ) {
var dy = p1.y - p2.y, let dy = p1.y - p2.y,
dz = p1.z - p2.z, dz = p1.z - p2.z,
pct = (p1.y - y) / dy, pct = (p1.y - y) / dy,
nz = p1.z - (dz * pct); nz = p1.z - (dz * pct);
@ -461,11 +535,9 @@ var gs_kiri_cam = exports;
// do x linear finishing // do x linear finishing
if (proc.finishingXOn) { if (proc.finishingXOn) {
startTime = time(); startTime = time();
// emit slice per X // emit slice per X
gridx = 0; gridx = 0;
for (x = bounds.min.x; x <= bounds.max.x; x += toolStep) { for (x = bounds.min.x; x <= bounds.max.x; x += toolStep) {
// for (x = bounds.min.x; x <= bounds.max.x; x += resolution) {
ly = gridy = 0; ly = gridy = 0;
slice = newSlice(gridx, mesh.newGroup ? mesh.newGroup() : null); slice = newSlice(gridx, mesh.newGroup ? mesh.newGroup() : null);
slice.camMode = CPRO.FINISH_X; slice.camMode = CPRO.FINISH_X;
@ -481,7 +553,7 @@ var gs_kiri_cam = exports;
newPoint(x,ly,lv), newPoint(x,ly,lv),
newPoint(x,y,gridv) newPoint(x,y,gridv)
)); ));
var ang = Math.abs((Math.atan2(ltv - tv, resolution) * R2A) % 90); let ang = Math.abs((Math.atan2(ltv - tv, resolution) * R2A) % 90);
// over max angle, turn into square edge (up or down) // over max angle, turn into square edge (up or down)
if (ang > maxangle) { if (ang > maxangle) {
if (ltv > tv) { if (ltv > tv) {
@ -499,7 +571,9 @@ var gs_kiri_cam = exports;
ltv = tv; ltv = tv;
gridy++; gridy++;
} }
if (cleanupTopoSlice(slice,diameter,curvesOnly)) newslices.push(slice); if (cleanupTopoSlice(slice,diameter,curvesOnly)) {
newslices.push(slice);
}
gridx = Math.round(((x - bounds.min.x + toolStep) / boundsX) * stepsx); gridx = Math.round(((x - bounds.min.x + toolStep) / boundsX) * stepsx);
onupdate(0.70 + (gridx/stepsx) * 0.15, "linear x"); onupdate(0.70 + (gridx/stepsx) * 0.15, "linear x");
} }
@ -508,7 +582,6 @@ var gs_kiri_cam = exports;
// do y linear finishing // do y linear finishing
if (proc.finishingYOn) { if (proc.finishingYOn) {
startTime = time(); startTime = time();
// emit slice per Y // emit slice per Y
gridy = 0; gridy = 0;
for (y = bounds.min.y; y < bounds.max.y; y += toolStep) { for (y = bounds.min.y; y < bounds.max.y; y += toolStep) {
@ -527,7 +600,7 @@ var gs_kiri_cam = exports;
newPoint(lx,y,lv), newPoint(lx,y,lv),
newPoint(x,y,gridv) newPoint(x,y,gridv)
)); ));
var ang = Math.abs((Math.atan2(ltv - tv, resolution) * R2A) % 90); let ang = Math.abs((Math.atan2(ltv - tv, resolution) * R2A) % 90);
// over max angle, turn into square edge (up or down) // over max angle, turn into square edge (up or down)
if (ang > maxangle) { if (ang > maxangle) {
if (ltv > tv) { if (ltv > tv) {
@ -545,7 +618,9 @@ var gs_kiri_cam = exports;
ltv = tv; ltv = tv;
gridx++; gridx++;
} }
if (cleanupTopoSlice(slice,diameter,curvesOnly)) newslices.push(slice); if (cleanupTopoSlice(slice,diameter,curvesOnly)) {
newslices.push(slice);
}
gridy = Math.round(((y - bounds.min.y + toolStep) / boundsY) * stepsy); gridy = Math.round(((y - bounds.min.y + toolStep) / boundsY) * stepsy);
onupdate(0.85 + (gridy/stepsy) * 0.15, "linear y"); onupdate(0.85 + (gridy/stepsy) * 0.15, "linear y");
} }
@ -572,7 +647,7 @@ var gs_kiri_cam = exports;
* @returns {Object} shell * @returns {Object} shell
*/ */
function createFacingSlices(slice, shell, diameter, overlap, pocket) { function createFacingSlices(slice, shell, diameter, overlap, pocket) {
var outer = [], let outer = [],
offset = []; offset = [];
// clone and flatten the shell with tops to offset array // clone and flatten the shell with tops to offset array
@ -610,7 +685,7 @@ var gs_kiri_cam = exports;
* @returns {Object} shell or newly generated shell * @returns {Object} shell or newly generated shell
*/ */
function createRoughingSlices(slice, shell, diameter, stock, overlap, pocket) { function createRoughingSlices(slice, shell, diameter, stock, overlap, pocket) {
var tops = slice.gatherTopPolys([]).clone(true), let tops = slice.gatherTopPolys([]).clone(true),
outer = [], outer = [],
offset = []; offset = [];
@ -656,7 +731,7 @@ var gs_kiri_cam = exports;
function createFinishingSlices(slice, shell, diameter, pocket) { function createFinishingSlices(slice, shell, diameter, pocket) {
if (slice.tops.length === 0) return shell; if (slice.tops.length === 0) return shell;
var tops = slice.gatherTopPolys([]).clone(true), let tops = slice.gatherTopPolys([]).clone(true),
offset = POLY.expand(tops, diameter / 2, slice.z); offset = POLY.expand(tops, diameter / 2, slice.z);
// when pocket only, drop first outer poly // when pocket only, drop first outer poly
@ -664,7 +739,7 @@ var gs_kiri_cam = exports;
if (pocket) { if (pocket) {
offset = POLY.filter(POLY.diff(shell, offset, slice.z), [], function(poly) { offset = POLY.filter(POLY.diff(shell, offset, slice.z), [], function(poly) {
if (poly.area() < 1) return null; if (poly.area() < 1) return null;
for (var sp=0; sp<shell.length; sp++) { for (let sp=0; sp<shell.length; sp++) {
// eliminate shell only polys // eliminate shell only polys
if (poly.isEquivalent(shell[sp])) { if (poly.isEquivalent(shell[sp])) {
if (poly.inner) return poly.inner; if (poly.inner) return poly.inner;
@ -689,7 +764,7 @@ var gs_kiri_cam = exports;
* @param {Function} output * @param {Function} output
*/ */
function slice(settings, widget, onupdate, ondone) { function slice(settings, widget, onupdate, ondone) {
var conf = settings, let conf = settings,
proc = conf.process, proc = conf.process,
outp = conf.process, outp = conf.process,
sliceAll = widget.slices = [], sliceAll = widget.slices = [],
@ -711,7 +786,7 @@ var gs_kiri_cam = exports;
pocketOnlyFinish = outp.camPocketOnlyFinish, pocketOnlyFinish = outp.camPocketOnlyFinish,
// addTabs = proc.camTabsOn && !pocketOnly, // addTabs = proc.camTabsOn && !pocketOnly,
addTabsRough = procRough && proc.camTabsOn && !pocketOnlyRough, addTabsRough = procRough && proc.camTabsOn && !pocketOnlyRough,
addTabsFinish = anyFinish && proc.camTabsOn && !pocketOnlyFinish, addTabsFinish = procFinish && proc.camTabsOn && !pocketOnlyFinish,
tabWidth = proc.camTabsWidth * units, tabWidth = proc.camTabsWidth * units,
tabHeight = proc.camTabsHeight * units, tabHeight = proc.camTabsHeight * units,
mesh = widget.mesh, mesh = widget.mesh,
@ -736,7 +811,7 @@ var gs_kiri_cam = exports;
// no tops / traces // no tops / traces
if (slice.tops.length === 0) return; if (slice.tops.length === 0) return;
var trace, index, maxArea = 0, tmpArea; let trace, index, maxArea = 0, tmpArea;
// find trace with greatest area // find trace with greatest area
slice.tops[0].traces.forEach(function(trc, idx) { slice.tops[0].traces.forEach(function(trc, idx) {
@ -810,7 +885,7 @@ var gs_kiri_cam = exports;
// hollow area from top of stock to top of part // hollow area from top of stock to top of part
if (procFacing) { if (procFacing) {
var ztop = bounds.max.z, let ztop = bounds.max.z,
zpos = ztop + (outp.camZTopOffset * units), zpos = ztop + (outp.camZTopOffset * units),
zstep = proc.roughingDown * units; zstep = proc.roughingDown * units;
@ -830,28 +905,28 @@ var gs_kiri_cam = exports;
} }
if (procRough) { if (procRough) {
var selected = []; let selected = [];
selectSlices(slices, proc.roughingDown * units, CPRO.ROUGH, selected); selectSlices(slices, proc.roughingDown * units, CPRO.ROUGH, selected);
sliceAll.appendAll(selected); sliceAll.appendAll(selected);
} }
if (anyFinish) { if (procFinish) {
var selected = []; let selected = [];
selectSlices(slices, proc.finishingDown * units, CPRO.FINISH, selected); selectSlices(slices, proc.finishingDown * units, CPRO.FINISH, selected);
sliceAll.appendAll(selected); sliceAll.appendAll(selected);
} }
if (procDrill) { if (procDrill) {
var drills = [], let drills = [],
centerDiff = drillToolDiam * 0.1, centerDiff = drillToolDiam * 0.1,
area = (drillToolDiam/2) * (drillToolDiam/2) * Math.PI, area = (drillToolDiam/2) * (drillToolDiam/2) * Math.PI,
areaDelta = area * 0.05; areaDelta = area * 0.05;
slices.forEach(function(slice) { slices.forEach(function(slice) {
var inner = slice.gatherTopPolyInners([]); let inner = slice.gatherTopPolyInners([]);
inner.forEach(function(poly) { inner.forEach(function(poly) {
if (poly.circularity() >= 0.985 && Math.abs(poly.area() - area) <= areaDelta) { if (poly.circularity() >= 0.985 && Math.abs(poly.area() - area) <= areaDelta) {
var center = poly.circleCenter(), let center = poly.circleCenter(),
merged = false, merged = false,
closest = Infinity, closest = Infinity,
dist; dist;
@ -874,7 +949,7 @@ var gs_kiri_cam = exports;
// force all drill poly points to use center (average) point // force all drill poly points to use center (average) point
drills.forEach(function(drill) { drills.forEach(function(drill) {
var center = drill.center(true), let center = drill.center(true),
slice = newSlice(0,null); slice = newSlice(0,null);
drill.points.forEach(function(point) { drill.points.forEach(function(point) {
point.x = center.x; point.x = center.x;
@ -934,7 +1009,7 @@ var gs_kiri_cam = exports;
* @param {Object} [firstPoint] starting point * @param {Object} [firstPoint] starting point
*/ */
function printSetup(print, update, index, firstPoint) { function printSetup(print, update, index, firstPoint) {
var getTool = getToolById, let getTool = getToolById,
settings = print.settings, settings = print.settings,
device = settings.device, device = settings.device,
process = settings.process, process = settings.process,
@ -947,7 +1022,7 @@ var gs_kiri_cam = exports;
alignTop = settings.controller.alignTop; alignTop = settings.controller.alignTop;
if (widgetIndex >= widgetCount || !widget) return; if (widgetIndex >= widgetCount || !widget) return;
var slices = widget.slices, let slices = widget.slices,
bounds = widget.getCamBounds(settings), bounds = widget.getCamBounds(settings),
units = settings.controller.units === 'in' ? 25.4 : 1, units = settings.controller.units === 'in' ? 25.4 : 1,
hasStock = process.camStockZ && process.camStockX && process.camStockY, hasStock = process.camStockZ && process.camStockX && process.camStockY,
@ -1019,12 +1094,12 @@ var gs_kiri_cam = exports;
function emitDrills(polys) { function emitDrills(polys) {
polys = polys.slice(); polys = polys.slice();
for (;;) { for (;;) {
var closestDist = Infinity, let closestDist = Infinity,
closestI, closestI,
closest = null, closest = null,
dist; dist;
for (var i=0; i<polys.length; i++) { for (let i=0; i<polys.length; i++) {
if (!polys[i]) continue; if (!polys[i]) continue;
if ((dist = polys[i].first().distTo2D(printPoint)) < closestDist) { if ((dist = polys[i].first().distTo2D(printPoint)) < closestDist) {
closestDist = dist; closestDist = dist;
@ -1045,7 +1120,7 @@ var gs_kiri_cam = exports;
} }
function emitDrill(poly, down, lift, dwell) { function emitDrill(poly, down, lift, dwell) {
var remain = poly.first().z - poly.last().z, let remain = poly.first().z - poly.last().z,
points = [], points = [],
point = poly.first(); point = poly.first();
for (;;) { for (;;) {
@ -1096,10 +1171,10 @@ var gs_kiri_cam = exports;
cut = 0; cut = 0;
nextIsMove = false; nextIsMove = false;
} }
var rate = feedRate; let rate = feedRate;
// only when we have a previous point to compare to // only when we have a previous point to compare to
if (lastPoint) { if (lastPoint) {
var deltaXY = lastPoint.distTo2D(point), let deltaXY = lastPoint.distTo2D(point),
deltaZ = point.z - lastPoint.z, deltaZ = point.z - lastPoint.z,
absDeltaZ = Math.abs(deltaZ), absDeltaZ = Math.abs(deltaZ),
isMove = !cut; isMove = !cut;
@ -1122,7 +1197,7 @@ var gs_kiri_cam = exports;
} //else (TODO verify no else here b/c above could change isMove) } //else (TODO verify no else here b/c above could change isMove)
// move over things // move over things
if ((deltaXY > toolDiam || (deltaZ > toolDiam && deltaXY > tolerance)) && (isMove || absDeltaZ >= tolerance)) { if ((deltaXY > toolDiam || (deltaZ > toolDiam && deltaXY > tolerance)) && (isMove || absDeltaZ >= tolerance)) {
var maxz = MAX( let maxz = MAX(
getTopoZPathMax( getTopoZPathMax(
widget, widget,
toolProfile, toolProfile,
@ -1148,7 +1223,7 @@ var gs_kiri_cam = exports;
} }
// synth new plunge rate // synth new plunge rate
if (deltaZ <= -tolerance) { if (deltaZ <= -tolerance) {
var threshold = MIN(deltaXY / 2, absDeltaZ), let threshold = MIN(deltaXY / 2, absDeltaZ),
modifier = threshold / absDeltaZ; modifier = threshold / absDeltaZ;
if (threshold && modifier && deltaXY > tolerance) { if (threshold && modifier && deltaXY > tolerance) {
// use modifier to speed up long XY move plunge rates // use modifier to speed up long XY move plunge rates
@ -1177,7 +1252,7 @@ var gs_kiri_cam = exports;
printPoint = firstPoint || origin; printPoint = firstPoint || origin;
// accumulated data for depth-first optimiztions // accumulated data for depth-first optimiztions
var depthData = { let depthData = {
rough: [], rough: [],
finish: [], finish: [],
roughDiam: 0, roughDiam: 0,
@ -1202,7 +1277,7 @@ var gs_kiri_cam = exports;
spindle = Math.min(spindleMax, process.roughingSpindle); spindle = Math.min(spindleMax, process.roughingSpindle);
slice.tops.forEach(function(top) { slice.tops.forEach(function(top) {
if (!top.traces) return; if (!top.traces) return;
var polys = []; let polys = [];
top.traces.forEach(function (poly) { top.traces.forEach(function (poly) {
polys.push(poly); polys.push(poly);
if (poly.inner) { if (poly.inner) {
@ -1236,7 +1311,7 @@ var gs_kiri_cam = exports;
slice.tops.forEach(function(top) { slice.tops.forEach(function(top) {
if (!top.poly) return; if (!top.poly) return;
if (!top.traces) return; if (!top.traces) return;
var polys = []; let polys = [];
POLY.flatten(top.traces, []).forEach(function (poly) { POLY.flatten(top.traces, []).forEach(function (poly) {
if (depthFirst) poly = poly.clone(true); if (depthFirst) poly = poly.clone(true);
poly.layer = depthData.layer; poly.layer = depthData.layer;
@ -1264,7 +1339,7 @@ var gs_kiri_cam = exports;
// todo find closest next trace/trace-point // todo find closest next trace/trace-point
slice.tops.forEach(function(top) { slice.tops.forEach(function(top) {
if (!top.traces) return; if (!top.traces) return;
var polys = [], poly, emit; let polys = [], poly, emit;
top.traces.forEach(function (poly) { top.traces.forEach(function (poly) {
if (depthFirst) poly = poly.clone(true); if (depthFirst) poly = poly.clone(true);
polys.push({first:poly.first(), last:poly.last(), poly:poly}); polys.push({first:poly.first(), last:poly.last(), poly:poly});
@ -1302,7 +1377,7 @@ var gs_kiri_cam = exports;
setTool(process.roughingTool, process.roughingSpeed, process.roughingPlunge); setTool(process.roughingTool, process.roughingSpeed, process.roughingPlunge);
spindle = Math.min(spindleMax, process.roughingSpindle); spindle = Math.min(spindleMax, process.roughingSpindle);
printPoint = poly2polyDepthFirstEmit(depthData.rough, printPoint, function(poly, index, count, fromPoint) { printPoint = poly2polyDepthFirstEmit(depthData.rough, printPoint, function(poly, index, count, fromPoint) {
var last = null; let last = null;
if (easeDown && poly.isClosed()) { if (easeDown && poly.isClosed()) {
last = poly.forEachPointEaseDown(function(point, offset) { last = poly.forEachPointEaseDown(function(point, offset) {
camOut(point.clone(), offset > 0); camOut(point.clone(), offset > 0);
@ -1321,7 +1396,7 @@ var gs_kiri_cam = exports;
setTool(process.finishingTool, process.finishingSpeed, process.finishingPlunge); setTool(process.finishingTool, process.finishingSpeed, process.finishingPlunge);
spindle = Math.min(spindleMax, process.finishingSpindle); spindle = Math.min(spindleMax, process.finishingSpindle);
printPoint = poly2polyDepthFirstEmit(depthData.finish, printPoint, function(poly, index, count, fromPoint) { printPoint = poly2polyDepthFirstEmit(depthData.finish, printPoint, function(poly, index, count, fromPoint) {
var last = null; let last = null;
if (easeDown && poly.isClosed()) { if (easeDown && poly.isClosed()) {
last = poly.forEachPointEaseDown(function(point, offset) { last = poly.forEachPointEaseDown(function(point, offset) {
camOut(point.clone(), offset > 0); camOut(point.clone(), offset > 0);
@ -1340,9 +1415,9 @@ var gs_kiri_cam = exports;
setTool(process.finishingTool, process.finishingSpeed, process.finishingPlunge); setTool(process.finishingTool, process.finishingSpeed, process.finishingPlunge);
spindle = Math.min(spindleMax, process.finishingSpindle); spindle = Math.min(spindleMax, process.finishingSpindle);
// combined deferred linear x and y finishing // combined deferred linear x and y finishing
var linearxy = [].appendAll(depthData.linearx).appendAll(depthData.lineary); let linearxy = [].appendAll(depthData.linearx).appendAll(depthData.lineary);
printPoint = tip2tipEmit(linearxy, printPoint, function(el, point, count) { printPoint = tip2tipEmit(linearxy, printPoint, function(el, point, count) {
var poly = el.poly; let poly = el.poly;
if (poly.last() === point) poly.reverse(); if (poly.last() === point) poly.reverse();
poly.forEachPoint(function(point, pidx) { poly.forEachPoint(function(point, pidx) {
camOut(point.clone(), pidx > 0); camOut(point.clone(), pidx > 0);
@ -1355,7 +1430,7 @@ var gs_kiri_cam = exports;
// deferred linear x finishing // deferred linear x finishing
if (depthData.linearx.length > 0) if (depthData.linearx.length > 0)
printPoint = tip2tipEmit(depthData.linearx, printPoint, function(el, point, count) { printPoint = tip2tipEmit(depthData.linearx, printPoint, function(el, point, count) {
var poly = el.poly; let poly = el.poly;
if (poly.last() === point) poly.reverse(); if (poly.last() === point) poly.reverse();
poly.forEachPoint(function(point, pidx) { poly.forEachPoint(function(point, pidx) {
camOut(point.clone(), pidx > 0); camOut(point.clone(), pidx > 0);
@ -1365,7 +1440,7 @@ var gs_kiri_cam = exports;
// deferred linear y finishing // deferred linear y finishing
if (depthData.lineary.length > 0) if (depthData.lineary.length > 0)
printPoint = tip2tipEmit(depthData.lineary, printPoint, function(el, point, count) { printPoint = tip2tipEmit(depthData.lineary, printPoint, function(el, point, count) {
var poly = el.poly; let poly = el.poly;
if (poly.last() === point) poly.reverse(); if (poly.last() === point) poly.reverse();
poly.forEachPoint(function(point, pidx) { poly.forEachPoint(function(point, pidx) {
camOut(point.clone(), pidx > 0); camOut(point.clone(), pidx > 0);
@ -1395,11 +1470,11 @@ var gs_kiri_cam = exports;
* @returns {Array} gcode lines * @returns {Array} gcode lines
*/ */
function printExport(print, online) { function printExport(print, online) {
var widget = print.widgets[0]; let widget = print.widgets[0];
if (!widget) return; if (!widget) return;
var i, let i,
time = 0, time = 0,
lines = 0, lines = 0,
bytes = 0, bytes = 0,
@ -1482,7 +1557,7 @@ var gs_kiri_cam = exports;
} }
function add0(val) { function add0(val) {
var s = val.toString(), let s = val.toString(),
d = s.indexOf("."); d = s.indexOf(".");
if (d < 0) { if (d < 0) {
return s + '.0'; return s + '.0';
@ -1492,14 +1567,14 @@ var gs_kiri_cam = exports;
} }
function toolNameByNumber(number, tools) { function toolNameByNumber(number, tools) {
for (var i=0; i<tools.length; i++) { for (let i=0; i<tools.length; i++) {
if (tools[i].number === number) return tools[i].name; if (tools[i].number === number) return tools[i].name;
} }
return "unknown"; return "unknown";
} }
function moveTo(out) { function moveTo(out) {
var newpos = out.point; let newpos = out.point;
// no point == dwell // no point == dwell
// out.speed = time to dwell in ms // out.speed = time to dwell in ms
@ -1524,7 +1599,7 @@ var gs_kiri_cam = exports;
filterEmit(cmdToolChange, consts); filterEmit(cmdToolChange, consts);
} }
var speed = out.speed, let speed = out.speed,
feed = speed || spro.camFastFeed, feed = speed || spro.camFastFeed,
nl = [speed ? 'G1' : 'G0'], nl = [speed ? 'G1' : 'G0'],
dx = newpos.x - pos.x, dx = newpos.x - pos.x,