fix poly2polyemit logic bug from easedown overriding previously found closest point
This commit is contained in:
parent
b8e9649267
commit
120175cd77
6 changed files with 291 additions and 293 deletions
|
|
@ -14,16 +14,16 @@ export function tip2tipEmit(array, startPoint, emitter) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
found = null;
|
found = null;
|
||||||
mindist = Infinity;
|
mindist = Infinity;
|
||||||
array.forEach(function(el) {
|
array.forEach(function (el) {
|
||||||
if (el.delete) return;
|
if (el.delete) return;
|
||||||
dist = startPoint.distTo2D(el.first);
|
dist = startPoint.distTo2D(el.first);
|
||||||
if (dist < mindist) {
|
if (dist < mindist) {
|
||||||
found = {el:el, first:el.first, last:el.last};
|
found = { el: el, first: el.first, last: el.last };
|
||||||
mindist = dist;
|
mindist = dist;
|
||||||
}
|
}
|
||||||
dist = startPoint.distTo2D(el.last);
|
dist = startPoint.distTo2D(el.last);
|
||||||
if (dist < mindist) {
|
if (dist < mindist) {
|
||||||
found = {el:el, first:el.last, last:el.first};
|
found = { el: el, first: el.last, last: el.first };
|
||||||
mindist = dist;
|
mindist = dist;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -62,21 +62,21 @@ export function poly2polyEmit(array, startPoint, emitter, opt = {}) {
|
||||||
}
|
}
|
||||||
if (d2l < mindist && d2l < d2f && opt.swapdir !== false) {
|
if (d2l < mindist && d2l < d2f && opt.swapdir !== false) {
|
||||||
poly.reverse();
|
poly.reverse();
|
||||||
found = {poly:poly, index:0, point:poly.first()};
|
found = { poly: poly, index: 0, point: poly.first() };
|
||||||
mindist = d2l;
|
mindist = d2l;
|
||||||
} else if (d2f < mindist) {
|
} else if (d2f < mindist) {
|
||||||
found = {poly:poly, index:0, point:poly.first()};
|
found = { poly: poly, index: 0, point: poly.first() };
|
||||||
mindist = d2f;
|
mindist = d2f;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let area = poly.open ? 1 : poly.area();
|
let area = poly.open ? 1 : poly.area();
|
||||||
poly.forEachPoint(function(point, index) {
|
poly.forEachPoint(function (point, index) {
|
||||||
dist = opt.weight ?
|
dist = opt.weight ?
|
||||||
startPoint.distTo3D(point) * area * area :
|
startPoint.distTo3D(point) * area * area :
|
||||||
startPoint.distTo2D(point);
|
startPoint.distTo2D(point);
|
||||||
if (dist < mindist) {
|
if (dist < mindist) {
|
||||||
found = {poly:poly, index:index, point:point};
|
found = { poly: poly, index: index, point: point };
|
||||||
mindist = dist;
|
mindist = dist;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -90,7 +90,7 @@ export function poly2polyEmit(array, startPoint, emitter, opt = {}) {
|
||||||
|
|
||||||
// undo delete marks
|
// undo delete marks
|
||||||
if (opt.perm !== true) {
|
if (opt.perm !== true) {
|
||||||
array.forEach(function(poly) { poly[marker] = false });
|
array.forEach(function (poly) { poly[marker] = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
return startPoint;
|
return startPoint;
|
||||||
|
|
@ -103,7 +103,7 @@ export function calc_normal(p1, p2) {
|
||||||
let mn = (1 / len);
|
let mn = (1 / len);
|
||||||
dx *= mn;
|
dx *= mn;
|
||||||
dy *= mn;
|
dy *= mn;
|
||||||
return({ dx: dy, dy: -dx, p1, p2, len });
|
return ({ dx: dy, dy: -dx, p1, p2, len });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function end_vertex(n1, n2, off, start) {
|
export function end_vertex(n1, n2, off, start) {
|
||||||
|
|
@ -159,10 +159,10 @@ export function pointsToPath(points, offset, open, miter = 1.5) {
|
||||||
const nupoints = [];
|
const nupoints = [];
|
||||||
const length = points.length;
|
const length = points.length;
|
||||||
if (length === 2 && points[0].isEqual(points[1])) {
|
if (length === 2 && points[0].isEqual(points[1])) {
|
||||||
return { };
|
return {};
|
||||||
}
|
}
|
||||||
const dedup = (open && length > 2) || (!open && length > 3);
|
const dedup = (open && length > 2) || (!open && length > 3);
|
||||||
for (let i=0; i<length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
let p1 = points[i];
|
let p1 = points[i];
|
||||||
let p2 = points[(i + 1) % length];
|
let p2 = points[(i + 1) % length];
|
||||||
p1.normal = calc_normal(p1, p2);
|
p1.normal = calc_normal(p1, p2);
|
||||||
|
|
@ -179,7 +179,7 @@ export function pointsToPath(points, offset, open, miter = 1.5) {
|
||||||
nupoints.push(p1);
|
nupoints.push(p1);
|
||||||
}
|
}
|
||||||
if (nupoints.length === 1) {
|
if (nupoints.length === 1) {
|
||||||
console.log({points, nupoints});
|
console.log({ points, nupoints });
|
||||||
}
|
}
|
||||||
// when points are dropped, we need the new array
|
// when points are dropped, we need the new array
|
||||||
points = nupoints;
|
points = nupoints;
|
||||||
|
|
@ -192,10 +192,10 @@ export function pointsToPath(points, offset, open, miter = 1.5) {
|
||||||
// calculate vertex normals from segments normals
|
// calculate vertex normals from segments normals
|
||||||
// vertex info is associated with the origin point
|
// vertex info is associated with the origin point
|
||||||
let fl, fr;
|
let fl, fr;
|
||||||
for (let i=0, l=points.length; i<l; i++) {
|
for (let i = 0, l = points.length; i < l; i++) {
|
||||||
let n1 = points[(i+l-1)%l].normal;
|
let n1 = points[(i + l - 1) % l].normal;
|
||||||
let n2 = points[(i+l)%l].normal;
|
let n2 = points[(i + l) % l].normal;
|
||||||
let vn = open && (i === 0 || i === l-1) ?
|
let vn = open && (i === 0 || i === l - 1) ?
|
||||||
end_vertex(n1, n2, offset, i === 0) :
|
end_vertex(n1, n2, offset, i === 0) :
|
||||||
calc_vertex(n1, n2, offset);
|
calc_vertex(n1, n2, offset);
|
||||||
let { p1, p2 } = n2;
|
let { p1, p2 } = n2;
|
||||||
|
|
@ -217,7 +217,7 @@ export function pointsToPath(points, offset, open, miter = 1.5) {
|
||||||
// shorten each leg and insert new point
|
// shorten each leg and insert new point
|
||||||
let delta = 0.1;
|
let delta = 0.1;
|
||||||
let np1 = p1.clone().move({ x: n1.dy * delta, y: -n1.dx * delta, z: 0 });
|
let np1 = p1.clone().move({ x: n1.dy * delta, y: -n1.dx * delta, z: 0 });
|
||||||
let np2 = p1.clone().move({ x:-n2.dy * delta, y: n2.dx * delta, z: 0 });
|
let np2 = p1.clone().move({ x: -n2.dy * delta, y: n2.dx * delta, z: 0 });
|
||||||
let sn1 = np1.normal = calc_normal(np1, np2);
|
let sn1 = np1.normal = calc_normal(np1, np2);
|
||||||
let sn2 = np2.normal = p1.normal;
|
let sn2 = np2.normal = p1.normal;
|
||||||
let nv1 = calc_vertex(n1.p1.normal, sn1, offset, np1);
|
let nv1 = calc_vertex(n1.p1.normal, sn1, offset, np1);
|
||||||
|
|
@ -344,14 +344,14 @@ export function pathTo3D(path, height, z) {
|
||||||
}
|
}
|
||||||
nrm.appendAll(normals);
|
nrm.appendAll(normals);
|
||||||
// reverse normals to match faces, but underside so reverse Z as well
|
// reverse normals to match faces, but underside so reverse Z as well
|
||||||
for (let i=normals.length-1; i>0; i-=3) {
|
for (let i = normals.length - 1; i > 0; i -= 3) {
|
||||||
nrm.push(normals[i-2]);
|
nrm.push(normals[i - 2]);
|
||||||
nrm.push(normals[i-1]);
|
nrm.push(normals[i - 1]);
|
||||||
nrm.push(-normals[i-0]);
|
nrm.push(-normals[i - 0]);
|
||||||
}
|
}
|
||||||
for (let i=0, l=left.length, tl = open ? l-1 : l; i<tl; i++) {
|
for (let i = 0, l = left.length, tl = open ? l - 1 : l; i < tl; i++) {
|
||||||
let p0 = left[i];
|
let p0 = left[i];
|
||||||
let p1 = left[(i+1)%l];
|
let p1 = left[(i + 1) % l];
|
||||||
out.push(p0.x, p0.y, p0.z + height);
|
out.push(p0.x, p0.y, p0.z + height);
|
||||||
out.push(p0.x, p0.y, p0.z - height);
|
out.push(p0.x, p0.y, p0.z - height);
|
||||||
out.push(p1.x, p1.y, p1.z - height);
|
out.push(p1.x, p1.y, p1.z - height);
|
||||||
|
|
@ -366,9 +366,9 @@ export function pathTo3D(path, height, z) {
|
||||||
nrm.push(ln.dx, ln.dy, -1);
|
nrm.push(ln.dx, ln.dy, -1);
|
||||||
nrm.push(ln.dx, ln.dy, -1);
|
nrm.push(ln.dx, ln.dy, -1);
|
||||||
}
|
}
|
||||||
for (let i=0, l=right.length, tl = open ? l-1 : l; i<tl; i++) {
|
for (let i = 0, l = right.length, tl = open ? l - 1 : l; i < tl; i++) {
|
||||||
let p0 = right[i];
|
let p0 = right[i];
|
||||||
let p1 = right[(i+1)%l];
|
let p1 = right[(i + 1) % l];
|
||||||
out.push(p0.x, p0.y, p0.z + height);
|
out.push(p0.x, p0.y, p0.z + height);
|
||||||
out.push(p1.x, p1.y, p1.z - height);
|
out.push(p1.x, p1.y, p1.z - height);
|
||||||
out.push(p0.x, p0.y, p0.z - height);
|
out.push(p0.x, p0.y, p0.z - height);
|
||||||
|
|
@ -439,9 +439,9 @@ export function shapeToPath(shape, points, closed) {
|
||||||
let hA = halfAngle;
|
let hA = halfAngle;
|
||||||
let tA = v2.angle() + Math.PI * .5;
|
let tA = v2.angle() + Math.PI * .5;
|
||||||
|
|
||||||
if (!closed){
|
if (!closed) {
|
||||||
if (i == 0 || i == points.length - 1) {hA = Math.PI * .5;}
|
if (i == 0 || i == points.length - 1) { hA = Math.PI * .5; }
|
||||||
if (i == points.length - 1) {tA = v1.angle() - Math.PI * .5;}
|
if (i == points.length - 1) { tA = v1.angle() - Math.PI * .5; }
|
||||||
}
|
}
|
||||||
|
|
||||||
const shift = Math.tan(hA - Math.PI * .5);
|
const shift = Math.tan(hA - Math.PI * .5);
|
||||||
|
|
@ -476,7 +476,7 @@ export function shapeToPath(shape, points, closed) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = [];
|
const index = [];
|
||||||
const lastCorner = closed == false ? points.length - 1: points.length;
|
const lastCorner = closed == false ? points.length - 1 : points.length;
|
||||||
|
|
||||||
for (let i = 0; i < lastCorner; i++) {
|
for (let i = 0; i < lastCorner; i++) {
|
||||||
for (let j = 0; j < profile.count; j++) {
|
for (let j = 0; j < profile.count; j++) {
|
||||||
|
|
@ -512,7 +512,7 @@ export function shapeToPath(shape, points, closed) {
|
||||||
index.push(p8, p7, p5);
|
index.push(p8, p7, p5);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {index, faces};
|
return { index, faces };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -527,7 +527,7 @@ export function shapeToPath(shape, points, closed) {
|
||||||
*
|
*
|
||||||
* @return {Array<Point>} an array of points representing the arc.
|
* @return {Array<Point>} an array of points representing the arc.
|
||||||
*/
|
*/
|
||||||
export function arcToPath (start, end, arcdivs=24, opts) {
|
export function arcToPath(start, end, arcdivs = 24, opts) {
|
||||||
|
|
||||||
let { clockwise, center, radius } = opts;
|
let { clockwise, center, radius } = opts;
|
||||||
|
|
||||||
|
|
@ -547,7 +547,7 @@ export function arcToPath (start, end, arcdivs=24, opts) {
|
||||||
let pr2;
|
let pr2;
|
||||||
if (Math.abs(dst - radius) < 0.001) {
|
if (Math.abs(dst - radius) < 0.001) {
|
||||||
// center point radius
|
// center point radius
|
||||||
pr2 = { x: (end.x + start.x) / 2, y: (end.y + start.y) / 2};
|
pr2 = { x: (end.x + start.x) / 2, y: (end.y + start.y) / 2 };
|
||||||
} else {
|
} else {
|
||||||
// triangulate
|
// triangulate
|
||||||
pr2 = base.util.center2pr(start, end, radius, clockwise);
|
pr2 = base.util.center2pr(start, end, radius, clockwise);
|
||||||
|
|
@ -556,7 +556,7 @@ export function arcToPath (start, end, arcdivs=24, opts) {
|
||||||
center.y = pr2.y;
|
center.y = pr2.y;
|
||||||
center.r = radius;
|
center.r = radius;
|
||||||
} else {
|
} else {
|
||||||
console.log({malfomed_arc: {radius,center, clockwise, start, end}});
|
console.log({ malfomed_arc: { radius, center, clockwise, start, end } });
|
||||||
}
|
}
|
||||||
|
|
||||||
//deltas
|
//deltas
|
||||||
|
|
@ -569,10 +569,10 @@ export function arcToPath (start, end, arcdivs=24, opts) {
|
||||||
let a2 = Math.atan2(center.y - end.y, center.x - end.x) + Math.PI;
|
let a2 = Math.atan2(center.y - end.y, center.x - end.x) + Math.PI;
|
||||||
let ad = base.util.thetaDiff(a1, a2, clockwise); // angle difference in radians
|
let ad = base.util.thetaDiff(a1, a2, clockwise); // angle difference in radians
|
||||||
let samePoint = Math.abs(ad) < 0.001
|
let samePoint = Math.abs(ad) < 0.001
|
||||||
let ofFull = Math.abs(ad)/(2*Math.PI);
|
let ofFull = Math.abs(ad) / (2 * Math.PI);
|
||||||
let steps = samePoint? arcdivs : Math.max(Math.floor( arcdivs * ofFull),4);
|
let steps = samePoint ? arcdivs : Math.max(Math.floor(arcdivs * ofFull), 4);
|
||||||
let step = (samePoint? (Math.PI*2) : ad) / steps;
|
let step = (samePoint ? (Math.PI * 2) : ad) / steps;
|
||||||
let numPoints = steps/ step;
|
let numPoints = steps / step;
|
||||||
let zStart = start.z;
|
let zStart = start.z;
|
||||||
let zStep = dz / numPoints;
|
let zStep = dz / numPoints;
|
||||||
let rot = a1 + step;
|
let rot = a1 + step;
|
||||||
|
|
@ -591,9 +591,9 @@ export function arcToPath (start, end, arcdivs=24, opts) {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
let arr = [] // point accumulator
|
let arr = [] // point accumulator
|
||||||
for (let i=0; i<=steps-2; i++) {
|
for (let i = 0; i <= steps - 2; i++) {
|
||||||
if (isNaN(center.r) || isNaN(center.x) || isNaN(center.y)) {
|
if (isNaN(center.r) || isNaN(center.x) || isNaN(center.y)) {
|
||||||
console.log({malfomed_arc: {radius, clockwise, start, end}});
|
console.log({ malfomed_arc: { radius, clockwise, start, end } });
|
||||||
}
|
}
|
||||||
arr.push(newPoint(
|
arr.push(newPoint(
|
||||||
center.x + Math.cos(rot) * center.r,
|
center.x + Math.cos(rot) * center.r,
|
||||||
|
|
@ -626,7 +626,7 @@ export class FloatPacker {
|
||||||
this.array = nuarray;
|
this.array = nuarray;
|
||||||
this.size = nusize;
|
this.size = nusize;
|
||||||
}
|
}
|
||||||
for (let i=0; i<args; i++) {
|
for (let i = 0; i < args; i++) {
|
||||||
array[this.pos++] = arguments[i];
|
array[this.pos++] = arguments[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,16 +31,16 @@ export function cam_export(print, online) {
|
||||||
space = device.gcodeSpace ? ' ' : '',
|
space = device.gcodeSpace ? ' ' : '',
|
||||||
isRML = device.gcodeFExt?.toLowerCase() === 'rml',
|
isRML = device.gcodeFExt?.toLowerCase() === 'rml',
|
||||||
stripComments = device.gcodeStrip || false,
|
stripComments = device.gcodeStrip || false,
|
||||||
cmdToolChange = device.gcodeChange || [ "M6 T{tool}" ],
|
cmdToolChange = device.gcodeChange || ["M6 T{tool}"],
|
||||||
cmdSpindle = device.gcodeSpindle || [ "M3 S{speed}" ],
|
cmdSpindle = device.gcodeSpindle || ["M3 S{speed}"],
|
||||||
cmdDwell = device.gcodeDwell || [ "G4 P{time}" ],
|
cmdDwell = device.gcodeDwell || ["G4 P{time}"],
|
||||||
axis = { X: 'X', Y: 'Y', Z: 'Z', A: 'A', F: 'F', R: 'R', I: 'I', J: 'J' },
|
axis = { X: 'X', Y: 'Y', Z: 'Z', A: 'A', F: 'F', R: 'R', I: 'I', J: 'J' },
|
||||||
dev = settings.device,
|
dev = settings.device,
|
||||||
spro = settings.process,
|
spro = settings.process,
|
||||||
maxZd = spro.camFastFeedZ,
|
maxZd = spro.camFastFeedZ,
|
||||||
maxXYd = spro.camFastFeed,
|
maxXYd = spro.camFastFeed,
|
||||||
decimals = base.config.gcode_decimals || 3,
|
decimals = base.config.gcode_decimals || 3,
|
||||||
pos = { x:null, y:null, z:null, a:undefined, f:null, t:null, emit:null },
|
pos = { x: null, y: null, z: null, a: undefined, f: null, t: null, emit: null },
|
||||||
line,
|
line,
|
||||||
cidx,
|
cidx,
|
||||||
mode,
|
mode,
|
||||||
|
|
@ -51,13 +51,13 @@ export function cam_export(print, online) {
|
||||||
compact_output = false,
|
compact_output = false,
|
||||||
lasering = false,
|
lasering = false,
|
||||||
laserOp,
|
laserOp,
|
||||||
stock = settings.stock || { },
|
stock = settings.stock || {},
|
||||||
ztOff = stock.z - widget.track.top,
|
ztOff = stock.z - widget.track.top,
|
||||||
bounds = widget.getBoundingBox(),
|
bounds = widget.getBoundingBox(),
|
||||||
zmax = stock.z,
|
zmax = stock.z,
|
||||||
runbox = {
|
runbox = {
|
||||||
max: { x:-Infinity, y:-Infinity, z:-Infinity},
|
max: { x: -Infinity, y: -Infinity, z: -Infinity },
|
||||||
min: { x:Infinity, y:Infinity, z:Infinity}
|
min: { x: Infinity, y: Infinity, z: Infinity }
|
||||||
},
|
},
|
||||||
offset = {
|
offset = {
|
||||||
x: -origin.x,
|
x: -origin.x,
|
||||||
|
|
@ -73,10 +73,10 @@ export function cam_export(print, online) {
|
||||||
box: runbox,
|
box: runbox,
|
||||||
tool: 0,
|
tool: 0,
|
||||||
tool_name: "unknown",
|
tool_name: "unknown",
|
||||||
top: (offset ? dev.bedDepth : dev.bedDepth/2),
|
top: (offset ? dev.bedDepth : dev.bedDepth / 2),
|
||||||
left: (offset ? 0 : -dev.bedWidth/2),
|
left: (offset ? 0 : -dev.bedWidth / 2),
|
||||||
right: (offset ? dev.bedWidth : dev.bedWidth/2),
|
right: (offset ? dev.bedWidth : dev.bedWidth / 2),
|
||||||
bottom: (offset ? 0 : -dev.bedDepth/2),
|
bottom: (offset ? 0 : -dev.bedDepth / 2),
|
||||||
time_sec: 0,
|
time_sec: 0,
|
||||||
time_ms: 0,
|
time_ms: 0,
|
||||||
time: 0
|
time: 0
|
||||||
|
|
@ -96,9 +96,9 @@ export function cam_export(print, online) {
|
||||||
if (spos >= 0) {
|
if (spos >= 0) {
|
||||||
const left = line.substring(0, spos);
|
const left = line.substring(0, spos);
|
||||||
const right = '(' + line.substring(spos)
|
const right = '(' + line.substring(spos)
|
||||||
.replace(/; /g,'')
|
.replace(/; /g, '')
|
||||||
.replace(/;/g,'') + ')';
|
.replace(/;/g, '') + ')';
|
||||||
line = [ left, right ].join('');
|
line = [left, right].join('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output.append(line);
|
output.append(line);
|
||||||
|
|
@ -123,21 +123,21 @@ export function cam_export(print, online) {
|
||||||
if (!array) {
|
if (!array) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (typeof(array) === 'string') {
|
if (typeof (array) === 'string') {
|
||||||
array = array.split('\n');
|
array = array.split('\n');
|
||||||
}
|
}
|
||||||
for (i=0; i<array.length; i++) {
|
for (i = 0; i < array.length; i++) {
|
||||||
line = print.constReplace(array[i], consts);
|
line = print.constReplace(array[i], consts);
|
||||||
if (!isRML && stripComments && (cidx = line.indexOf(";")) >= 0) {
|
if (!isRML && stripComments && (cidx = line.indexOf(";")) >= 0) {
|
||||||
line = line.substring(0, cidx).trim();
|
line = line.substring(0, cidx).trim();
|
||||||
if (line.length === 0) continue;
|
if (line.length === 0) continue;
|
||||||
}
|
}
|
||||||
if (line.indexOf('G20') === 0) {
|
if (line.indexOf('G20') === 0) {
|
||||||
factor = 1/25.4;
|
factor = 1 / 25.4;
|
||||||
consts.top = (offset ? dev.bedDepth : dev.bedDepth/2) * factor;
|
consts.top = (offset ? dev.bedDepth : dev.bedDepth / 2) * factor;
|
||||||
consts.left = (offset ? 0 : -dev.bedWidth/2) * factor;
|
consts.left = (offset ? 0 : -dev.bedWidth / 2) * factor;
|
||||||
consts.right = (offset ? dev.bedWidth : dev.bedWidth/2) * factor;
|
consts.right = (offset ? dev.bedWidth : dev.bedWidth / 2) * factor;
|
||||||
consts.bottom = (offset ? 0 : -dev.bedDepth/2) * factor;
|
consts.bottom = (offset ? 0 : -dev.bedDepth / 2) * factor;
|
||||||
} else if (line.indexOf('G21') === 0) {
|
} else if (line.indexOf('G21') === 0) {
|
||||||
factor = 1;
|
factor = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -193,7 +193,7 @@ export function cam_export(print, online) {
|
||||||
consts.tool = pos.t.getNumber();
|
consts.tool = pos.t.getNumber();
|
||||||
consts.tool_name = pos.t.getName();
|
consts.tool_name = pos.t.getName();
|
||||||
if (!laserOp && (spro.camToolInit || toolChanges > 0)) {
|
if (!laserOp && (spro.camToolInit || toolChanges > 0)) {
|
||||||
filterEmit(cmdToolChange, { ...consts, spindle: newSpindle } );
|
filterEmit(cmdToolChange, { ...consts, spindle: newSpindle });
|
||||||
}
|
}
|
||||||
toolChanges++;
|
toolChanges++;
|
||||||
}
|
}
|
||||||
|
|
@ -259,7 +259,7 @@ export function cam_export(print, online) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let gn;
|
let gn;
|
||||||
if ( out.emit >=0 && out.emit <= 3) gn = `G${out.emit}`;
|
if (out.emit >= 0 && out.emit <= 3) gn = `G${out.emit}`;
|
||||||
let speed = out.speed,
|
let speed = out.speed,
|
||||||
arc = out.emit == 2 || out.emit == 3,
|
arc = out.emit == 2 || out.emit == 3,
|
||||||
center = out.center,
|
center = out.center,
|
||||||
|
|
@ -307,7 +307,7 @@ export function cam_export(print, online) {
|
||||||
pos.f = feed;
|
pos.f = feed;
|
||||||
nl.append(space).append(axis.F).append(add0(consts.feed = feed * factor, true));
|
nl.append(space).append(axis.F).append(add0(consts.feed = feed * factor, true));
|
||||||
}
|
}
|
||||||
if(arc){
|
if (arc) {
|
||||||
nl.append(space).append(axis.I).append(add0(center.x * factor, true))
|
nl.append(space).append(axis.I).append(add0(center.x * factor, true))
|
||||||
.append(space).append(axis.J).append(add0(center.y * factor, true));
|
.append(space).append(axis.J).append(add0(center.y * factor, true));
|
||||||
}
|
}
|
||||||
|
|
@ -318,9 +318,9 @@ export function cam_export(print, online) {
|
||||||
if (newFeed) {
|
if (newFeed) {
|
||||||
append(`VS${feed};`);
|
append(`VS${feed};`);
|
||||||
}
|
}
|
||||||
nl = [ axis.Z, add0(pos.x * factor), ",", add0(pos.y * factor), ",", add0(pos.z * factor), ";" ];
|
nl = [axis.Z, add0(pos.x * factor), ",", add0(pos.y * factor), ",", add0(pos.z * factor), ";"];
|
||||||
} else {
|
} else {
|
||||||
nl = [ "PU", add0(pos.x * factor), ",", add0(pos.y * factor), ";" ];
|
nl = ["PU", add0(pos.x * factor), ",", add0(pos.y * factor), ";"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ const { toRadians } = util
|
||||||
export async function cam_prepare(widall, settings, update) {
|
export async function cam_prepare(widall, settings, update) {
|
||||||
const widgets = widall.filter(w => !w.track.ignore && !w.meta.disabled);
|
const widgets = widall.filter(w => !w.track.ignore && !w.meta.disabled);
|
||||||
const count = widgets.length;
|
const count = widgets.length;
|
||||||
const weight = 1/count;
|
const weight = 1 / count;
|
||||||
const print = self.kiri_worker.current.print = newPrint(settings, widgets);
|
const print = self.kiri_worker.current.print = newPrint(settings, widgets);
|
||||||
print.output = [];
|
print.output = [];
|
||||||
|
|
||||||
|
|
@ -193,13 +193,13 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
|
|
||||||
function emitDrills(polys) {
|
function emitDrills(polys) {
|
||||||
polys = polys.slice();
|
polys = polys.slice();
|
||||||
for (;;) {
|
for (; ;) {
|
||||||
let closestDist = Infinity,
|
let closestDist = Infinity,
|
||||||
closestI,
|
closestI,
|
||||||
closest = null,
|
closest = null,
|
||||||
dist;
|
dist;
|
||||||
|
|
||||||
for (let 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;
|
||||||
|
|
@ -222,7 +222,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
if (down <= 0) {
|
if (down <= 0) {
|
||||||
down = remain;
|
down = remain;
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (; ;) {
|
||||||
if (remain > down * 2) {
|
if (remain > down * 2) {
|
||||||
points.push(point.clone());
|
points.push(point.clone());
|
||||||
point.z -= down;
|
point.z -= down;
|
||||||
|
|
@ -242,14 +242,14 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
camOut(point.clone().setZ(zmax));
|
camOut(point.clone().setZ(zmax));
|
||||||
points.forEach(function(point, index) {
|
points.forEach(function (point, index) {
|
||||||
camOut(point, 1);
|
camOut(point, 1);
|
||||||
if (index > 0 && index < points.length - 1) {
|
if (index > 0 && index < points.length - 1) {
|
||||||
if (dwell) camDwell(dwell);
|
if (dwell) camDwell(dwell);
|
||||||
if (lift) camOut(point.clone().setZ(point.z + lift), 0);
|
if (lift) camOut(point.clone().setZ(point.z + lift), 0);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
camOut(point.clone().setZ(zmax),0);
|
camOut(point.clone().setZ(zmax), 0);
|
||||||
newLayer();
|
newLayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -290,9 +290,9 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
if (lasering.flat) {
|
if (lasering.flat) {
|
||||||
point.z = (stock && stock.z ? stock.z : wztop) + lasering.flatz;
|
point.z = (stock && stock.z ? stock.z : wztop) + lasering.flatz;
|
||||||
}
|
}
|
||||||
print.addOutput(layerOut, point, power, speed, tool, {type:'laser'});
|
print.addOutput(layerOut, point, power, speed, tool, { type: 'laser' });
|
||||||
} else {
|
} else {
|
||||||
print.addOutput(layerOut, point, emit, speed, tool, {type, center, arcPoints});
|
print.addOutput(layerOut, point, emit, speed, tool, { type, center, arcPoints });
|
||||||
}
|
}
|
||||||
lastPush = { point, emit, speed, tool };
|
lastPush = { point, emit, speed, tool };
|
||||||
return point;
|
return point;
|
||||||
|
|
@ -312,7 +312,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
* @param {Point} p - point to move
|
* @param {Point} p - point to move
|
||||||
* @return {Point} new point with offset applied
|
* @return {Point} new point with offset applied
|
||||||
*/
|
*/
|
||||||
function applyWidgetMovement(p){
|
function applyWidgetMovement(p) {
|
||||||
return newPoint(
|
return newPoint(
|
||||||
p.x + wmx,
|
p.x + wmx,
|
||||||
p.y + wmy,
|
p.y + wmy,
|
||||||
|
|
@ -329,8 +329,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
* @param {number} opts.moveLen typically = tool diameter used to trigger terrain detection
|
* @param {number} opts.moveLen typically = tool diameter used to trigger terrain detection
|
||||||
* @param {number} opts.factor speed scale factor
|
* @param {number} opts.factor speed scale factor
|
||||||
*/
|
*/
|
||||||
function camOut(point, emit,opts) {
|
function camOut(point, emit, opts) {
|
||||||
|
|
||||||
// console.log({point, emit, opts})
|
// console.log({point, emit, opts})
|
||||||
let {
|
let {
|
||||||
center = {},
|
center = {},
|
||||||
|
|
@ -374,7 +373,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
emit,
|
emit,
|
||||||
rate,
|
rate,
|
||||||
tool,
|
tool,
|
||||||
{type:"lerp"},
|
{ type: "lerp" },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -401,7 +400,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert short planar moves to cuts in some cases
|
// convert short planar moves to cuts in some cases
|
||||||
if (!isRough&& !isArc && isMove && deltaXY <= moveLen && deltaZ <= 0 && !lasering ) {
|
if (!isRough && !isArc && isMove && deltaXY <= moveLen && deltaZ <= 0 && !lasering) {
|
||||||
let iscontour = tolerance > 0;
|
let iscontour = tolerance > 0;
|
||||||
let isflat = absDeltaZ < 0.001;
|
let isflat = absDeltaZ < 0.001;
|
||||||
// restrict this to contouring
|
// restrict this to contouring
|
||||||
|
|
@ -423,7 +422,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
} else if (isMove) {
|
} else if (isMove) {
|
||||||
// for longer moves, check the terrain to see if we need to go up and over
|
// for longer moves, check the terrain to see if we need to go up and over
|
||||||
const bigXY = (deltaXY > moveLen && !lasering);
|
const bigXY = (deltaXY > moveLen && !lasering);
|
||||||
const bigZ = (deltaZ > toolDiam/2 && deltaXY > tolerance);
|
const bigZ = (deltaZ > toolDiam / 2 && deltaXY > tolerance);
|
||||||
const midZ = (tolerance && absDeltaZ >= tolerance) && !isContour;
|
const midZ = (tolerance && absDeltaZ >= tolerance) && !isContour;
|
||||||
|
|
||||||
if (bigXY || bigZ || midZ) {
|
if (bigXY || bigZ || midZ) {
|
||||||
|
|
@ -435,7 +434,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
point.y - wmy,
|
point.y - wmy,
|
||||||
Math.max(point.z, lastPoint.z),
|
Math.max(point.z, lastPoint.z),
|
||||||
zadd,
|
zadd,
|
||||||
maxToolDiam/2,
|
maxToolDiam / 2,
|
||||||
zclear
|
zclear
|
||||||
),
|
),
|
||||||
maxZdelta = Math.max(maxz - point.z, maxz - lastPoint.z),
|
maxZdelta = Math.max(maxz - point.z, maxz - lastPoint.z),
|
||||||
|
|
@ -471,7 +470,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
rate = Math.round(plungeRate + ((feedRate - plungeRate) * modifier));
|
rate = Math.round(plungeRate + ((feedRate - plungeRate) * modifier));
|
||||||
cut = 1;
|
cut = 1;
|
||||||
} else {
|
} else {
|
||||||
rate = 1 / Math.hypot(deltaXY / feedRate , absDeltaZ / plungeRate );
|
rate = 1 / Math.hypot(deltaXY / feedRate, absDeltaZ / plungeRate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -534,8 +533,8 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
depthData.push(polys);
|
depthData.push(polys);
|
||||||
} else {
|
} else {
|
||||||
// if not depth first, output the polys in slice order
|
// if not depth first, output the polys in slice order
|
||||||
printPoint = poly2polyEmit(polys, printPoint, function(poly, index, count) {
|
printPoint = poly2polyEmit(polys, printPoint, function (poly, index, count) {
|
||||||
poly.forEachPoint(function(point, pidx, points, offset) {
|
poly.forEachPoint(function (point, pidx, points, offset) {
|
||||||
// scale speed of first cutting poly since it engages the full bit
|
// scale speed of first cutting poly since it engages the full bit
|
||||||
camOut(point.clone(), offset !== 0, undefined, count === 1 ? engageFactor : 1);
|
camOut(point.clone(), offset !== 0, undefined, count === 1 ? engageFactor : 1);
|
||||||
}, poly.isClosed(), index);
|
}, poly.isClosed(), index);
|
||||||
|
|
@ -547,7 +546,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
|
|
||||||
// crucially returns true for -0 as well as other negative #s
|
// crucially returns true for -0 as well as other negative #s
|
||||||
function isNeg(v) {
|
function isNeg(v) {
|
||||||
return v < 0 || (v === 0 && 1/v === -Infinity);
|
return v < 0 || (v === 0 && 1 / v === -Infinity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depthFirst) {
|
if (depthFirst) {
|
||||||
|
|
@ -571,7 +570,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
* 1. Travel from fromPoint to closest point on polygon, to rampZ above that that point,
|
* 1. Travel from fromPoint to closest point on polygon, to rampZ above that that point,
|
||||||
* 2. ease-down starts, following the polygonal path, decreasing Z at a fixed slope until target Z is hit,
|
* 2. ease-down starts, following the polygonal path, decreasing Z at a fixed slope until target Z is hit,
|
||||||
*/
|
*/
|
||||||
function generateEaseDown(fn,poly, fromPoint, degrees = 45){
|
function generateEaseDown(fn, poly, fromPoint, degrees = 45) {
|
||||||
let index = poly.findClosestPointTo(fromPoint).index,
|
let index = poly.findClosestPointTo(fromPoint).index,
|
||||||
fromZ = fromPoint.z,
|
fromZ = fromPoint.z,
|
||||||
offset = 0,
|
offset = 0,
|
||||||
|
|
@ -677,7 +676,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
};
|
};
|
||||||
|
|
||||||
let opSum = 0;
|
let opSum = 0;
|
||||||
let opTot = widget.camops.map(op => op.weight()).reduce((a,v) => a + v);
|
let opTot = widget.camops.map(op => op.weight()).reduce((a, v) => a + v);
|
||||||
|
|
||||||
for (let op of widget.camops) {
|
for (let op of widget.camops) {
|
||||||
setTolerance(0);
|
setTolerance(0);
|
||||||
|
|
@ -729,95 +728,90 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
* @returns {Point} - the last point of the polygon
|
* @returns {Point} - the last point of the polygon
|
||||||
*/
|
*/
|
||||||
function polyEmit(poly, index, count, fromPoint) {
|
function polyEmit(poly, index, count, fromPoint) {
|
||||||
|
let arcQ = [],
|
||||||
let arcMax = Infinity, // no max arc radius
|
arcMax = Infinity, // no max arc radius
|
||||||
lineTolerance = 0.001; // do not consider points under 0.001mm for arcs
|
lineTolerance = 0.001; // do not consider points under 0.001mm for arcs
|
||||||
|
|
||||||
fromPoint = fromPoint || printPoint;
|
fromPoint = fromPoint || printPoint;
|
||||||
let arcQ = [];
|
|
||||||
arcQ.angle = []
|
arcQ.angle = []
|
||||||
|
|
||||||
let closest = poly.findClosestPointTo(fromPoint);
|
let lastPoint = fromPoint;
|
||||||
let lastPoint = closest.point;
|
let startIndex = index;
|
||||||
let startIndex = closest.index;
|
|
||||||
|
|
||||||
// console.log({poly, index, count, fromPoint,startIndex})
|
// console.log({poly, index, count, fromPoint, startIndex})
|
||||||
|
|
||||||
// scale speed of first cutting poly since it engages the full bit
|
// scale speed of first cutting poly since it engages the full bit
|
||||||
let scale = ((isRough || isPocket) && count === 1) ? engageFactor : 1;
|
let scale = ((isRough || isPocket) && count === 1) ? engageFactor : 1;
|
||||||
|
|
||||||
|
// easeDown only allowed on closed polys (that we can continue around indefinitly)
|
||||||
if (easeDown && poly.isClosed()) { //if doing ease-down
|
if (easeDown && poly.isClosed()) {
|
||||||
|
let closest = poly.findClosestPointTo(fromPoint);
|
||||||
let last = generateEaseDown((point,offset )=>{ //generate ease-down points
|
lastPoint = closest.point;
|
||||||
if(offset == 0) camOut(point.clone(), 0, {factor:engageFactor});
|
startIndex = closest.index;
|
||||||
camOut(point.clone(), 1, {factor:scale}); // and pass them to camOut
|
let last = generateEaseDown((point, offset) => { // generate ease-down points
|
||||||
|
if (offset == 0) camOut(point.clone(), 0, { factor: engageFactor });
|
||||||
|
camOut(point.clone(), 1, { factor: scale }); // and pass them to camOut
|
||||||
}, poly, fromPoint, easeAngle);
|
}, poly, fromPoint, easeAngle);
|
||||||
lastPoint = poly.points[last];
|
lastPoint = poly.points[last];
|
||||||
startIndex = last;
|
startIndex = last;
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.log(poly,poly.isClosed(),startIndex)
|
// console.log(poly,poly.isClosed(),startIndex)
|
||||||
//A is first point of segment, B is last
|
// A is first point of segment, B is last
|
||||||
poly.forEachSegment( ( pointA, pointB, indexA, indexB) => {
|
poly.forEachSegment((pointA, pointB, indexA, indexB) => {
|
||||||
// if(offset == 0) console.log("forEachPoint",point,pidx,points)
|
// if(offset == 0) console.log("forEachPoint",point,pidx,points)
|
||||||
// console.log({pointA, pointB, indexA, indexB,startIndex})
|
// console.log({pointA, pointB, indexA, indexB,startIndex})
|
||||||
if(indexA == startIndex){
|
if (indexA == startIndex) {
|
||||||
camOut(pointA.clone(), 0, {factor:engageFactor});
|
camOut(pointA.clone(), 0, { factor: engageFactor });
|
||||||
// if first point, move to and call export function
|
// if first point, move to and call export function
|
||||||
quePush(pointA);
|
arcQ.push(pointA);
|
||||||
}
|
}
|
||||||
lastPoint = arcExport(pointB, pointA);
|
lastPoint = arcExport(pointB, pointA);
|
||||||
}, !poly.isClosed(), startIndex);
|
}, !poly.isClosed(), startIndex);
|
||||||
|
|
||||||
// console.log("at end of arcExport",structuredClone(arcQ));
|
// console.log("at end of arcExport",structuredClone(arcQ));
|
||||||
if(arcQ.length > 3){
|
if (arcQ.length > 3) {
|
||||||
//if few points left, emit as lines
|
// if few points left, emit as lines
|
||||||
drainQ();
|
drainQ();
|
||||||
}
|
}
|
||||||
while (arcQ.length){
|
while (arcQ.length) {
|
||||||
camOut(arcQ.shift(),1);
|
camOut(arcQ.shift(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function quePush(point){
|
function arcExport(point, lastp) {
|
||||||
arcQ.push(point);
|
let dist = lastp ? point.distTo2D(lastp) : 0;
|
||||||
}
|
|
||||||
|
|
||||||
function arcExport(point,lastp){
|
|
||||||
let dist = lastp? point.distTo2D(lastp) : 0;
|
|
||||||
if (lastp) {
|
if (lastp) {
|
||||||
if (dist >lineTolerance && lastp) {
|
if (dist > lineTolerance && lastp) {
|
||||||
let rec = Object.assign(point,{dist});
|
let rec = Object.assign(point, { dist });
|
||||||
arcQ.push(rec);
|
arcQ.push(rec);
|
||||||
|
|
||||||
// ondebug({arcQ});
|
// ondebug({arcQ});
|
||||||
if (arcQ.length > 2) {
|
if (arcQ.length > 2) {
|
||||||
let el = arcQ.length;
|
let el = arcQ.length;
|
||||||
let e1 = arcQ[0]; // first in arcQ
|
let e1 = arcQ[0]; // first in arcQ
|
||||||
let e2 = arcQ[Math.floor(el/2)]; // mid in arcQ
|
let e2 = arcQ[Math.floor(el / 2)]; // mid in arcQ
|
||||||
let e3 = arcQ[el-1]; // last in arcQ
|
let e3 = arcQ[el - 1]; // last in arcQ
|
||||||
let e4 = arcQ[el-2]; // second last in arcQ
|
let e4 = arcQ[el - 2]; // second last in arcQ
|
||||||
let e5 = arcQ[el-3]; // third last in arcQ
|
let e5 = arcQ[el - 3]; // third last in arcQ
|
||||||
let cc = util.center2d(e1, e2, e3, 1); // find center
|
let cc = util.center2d(e1, e2, e3, 1); // find center
|
||||||
let lr = util.center2d(e3, e4, e5, 1); // find local radius
|
let lr = util.center2d(e3, e4, e5, 1); // find local radius
|
||||||
let dc = 0;
|
let dc = 0;
|
||||||
|
|
||||||
let radFault = false;
|
let radFault = false;
|
||||||
if (lr) {
|
if (lr) {
|
||||||
let angle = 2 * Math.asin(dist/(2*lr.r));
|
let angle = 2 * Math.asin(dist / (2 * lr.r));
|
||||||
radFault = Math.abs(angle) > arcRes; // enforce arcRes(olution)
|
radFault = Math.abs(angle) > arcRes; // enforce arcRes(olution)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
radFault = true;
|
|
||||||
// console.log("too much angle")
|
// console.log("too much angle")
|
||||||
|
radFault = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cc) {
|
if (cc) {
|
||||||
if ([cc.x,cc.y,cc.z,cc.r].hasNaN()) {
|
if ([cc.x, cc.y, cc.z, cc.r].hasNaN()) {
|
||||||
// console.log({cc, e1, e2, e3});
|
// console.log({cc, e1, e2, e3});
|
||||||
}
|
}
|
||||||
if (arcQ.length === 3) {
|
if (arcQ.length === 3) {
|
||||||
arcQ.center = [ cc ];
|
arcQ.center = [cc];
|
||||||
arcQ.xSum = cc.x;
|
arcQ.xSum = cc.x;
|
||||||
arcQ.ySum = cc.y;
|
arcQ.ySum = cc.y;
|
||||||
arcQ.rSum = cc.r;
|
arcQ.rSum = cc.r;
|
||||||
|
|
@ -825,39 +819,39 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
// check if first angles should have caused radFault
|
// check if first angles should have caused radFault
|
||||||
let a = toRadians(arcQ[0].slopeTo(cc).angle)
|
let a = toRadians(arcQ[0].slopeTo(cc).angle)
|
||||||
let b = toRadians(arcQ[1].slopeTo(cc).angle)
|
let b = toRadians(arcQ[1].slopeTo(cc).angle)
|
||||||
let angle = Math.abs(b-a)
|
let angle = Math.abs(b - a)
|
||||||
|
|
||||||
if( Math.abs(angle) > arcRes){
|
if (Math.abs(angle) > arcRes) {
|
||||||
// if so, remove first point
|
// if so, remove first point
|
||||||
camOut(arcQ.shift(), 1)
|
camOut(arcQ.shift(), 1)
|
||||||
radFault = true
|
radFault = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// check center point delta
|
// check center point delta
|
||||||
arcQ.xSum = arcQ.center.reduce( function (t, v) { return t + v.x }, 0 );
|
arcQ.xSum = arcQ.center.reduce(function (t, v) { return t + v.x }, 0);
|
||||||
arcQ.ySum = arcQ.center.reduce( function (t, v) { return t + v.y }, 0 );
|
arcQ.ySum = arcQ.center.reduce(function (t, v) { return t + v.y }, 0);
|
||||||
arcQ.rSum = arcQ.center.reduce( function (t, v) { return t + v.r }, 0 );
|
arcQ.rSum = arcQ.center.reduce(function (t, v) { return t + v.r }, 0);
|
||||||
let dx = cc.x - arcQ.xSum / arcQ.center.length;
|
let dx = cc.x - arcQ.xSum / arcQ.center.length;
|
||||||
let dy = cc.y - arcQ.ySum / arcQ.center.length;
|
let dy = cc.y - arcQ.ySum / arcQ.center.length;
|
||||||
dc = Math.hypot(dx, dy); // delta center distance
|
dc = Math.hypot(dx, dy); // delta center distance
|
||||||
}
|
}
|
||||||
// if new point is off the arc
|
// if new point is off the arc
|
||||||
// if (deem || depm || desp || dc > arcTolerance || cc.r < arcMin || cc.r > arcMax || dist > cc.r) {
|
// if (deem || depm || desp || dc > arcTolerance || cc.r < arcMin || cc.r > arcMax || dist > cc.r) {
|
||||||
if ( dc * arcQ.center.length / arcQ.rSum > arcTolerance || dist > cc.r || cc.r > arcMax || radFault ) {
|
if (dc * arcQ.center.length / arcQ.rSum > arcTolerance || dist > cc.r || cc.r > arcMax || radFault) {
|
||||||
// let debug = [deem, depm, desp, dc * arcQ.center.length / arcQ.rSum > arcTolerance, dist > cc.r, cc.r > arcMax, radFault];
|
// let debug = [deem, depm, desp, dc * arcQ.center.length / arcQ.rSum > arcTolerance, dist > cc.r, cc.r > arcMax, radFault];
|
||||||
// console.log("point off the arc,",structuredClone(arcQ),);
|
// console.log("point off the arc,",structuredClone(arcQ),);
|
||||||
if (arcQ.length === 4) {
|
if (arcQ.length === 4) {
|
||||||
// not enough points for an arc, drop first point and recalc center
|
// not enough points for an arc, drop first point and recalc center
|
||||||
camOut(arcQ.shift(),1);
|
camOut(arcQ.shift(), 1);
|
||||||
let tc = util.center2d(arcQ[0], arcQ[1], arcQ[2], 1);
|
let tc = util.center2d(arcQ[0], arcQ[1], arcQ[2], 1);
|
||||||
// the new center is invalid as well. drop the first point
|
// the new center is invalid as well. drop the first point
|
||||||
if (!tc) {
|
if (!tc) {
|
||||||
camOut(arcQ.shift(),1);
|
camOut(arcQ.shift(), 1);
|
||||||
} else {
|
} else {
|
||||||
arcQ.center = [ tc ];
|
arcQ.center = [tc];
|
||||||
let angle = 2 * Math.asin(arcQ[1].dist/(2*tc.r));
|
let angle = 2 * Math.asin(arcQ[1].dist / (2 * tc.r));
|
||||||
if (Math.abs(angle) > arcRes) { // enforce arcRes on initial angle
|
if (Math.abs(angle) > arcRes) { // enforce arcRes on initial angle
|
||||||
camOut(arcQ.shift(),1);
|
camOut(arcQ.shift(), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -883,7 +877,6 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if first point, emit and set
|
// if first point, emit and set
|
||||||
|
|
||||||
camOut(point, 1);
|
camOut(point, 1);
|
||||||
// TODO disabling out of plane z moves until a better mechanism
|
// TODO disabling out of plane z moves until a better mechanism
|
||||||
// can be built that doesn't rely on computed zpos from layer heights...
|
// can be built that doesn't rely on computed zpos from layer heights...
|
||||||
|
|
@ -895,24 +888,24 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function drainQ() {
|
function drainQ() {
|
||||||
|
|
||||||
let arcPreviewRes = 64
|
let arcPreviewRes = 64
|
||||||
|
|
||||||
if (!arcTolerance) {
|
if (!arcTolerance) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arcQ.length > 4) {
|
if (arcQ.length > 4) {
|
||||||
// ondebug({arcQ});
|
// ondebug({arcQ});
|
||||||
let vec1 = new THREE.Vector2(arcQ[1].x - arcQ[0].x, arcQ[1].y - arcQ[0].y);
|
let vec1 = new THREE.Vector2(arcQ[1].x - arcQ[0].x, arcQ[1].y - arcQ[0].y);
|
||||||
let vec2 = new THREE.Vector2(arcQ.center[0].x - arcQ[0].x, arcQ.center[0].y - arcQ[0].y);
|
let vec2 = new THREE.Vector2(arcQ.center[0].x - arcQ[0].x, arcQ.center[0].y - arcQ[0].y);
|
||||||
let clockwise = vec1.cross(vec2) < 0
|
let clockwise = vec1.cross(vec2) < 0
|
||||||
let gc = clockwise ? 2 :3
|
let gc = clockwise ? 2 : 3
|
||||||
let from = arcQ[0];
|
let from = arcQ[0];
|
||||||
let to = arcQ.peek();
|
let to = arcQ.peek();
|
||||||
let delta = from.distTo2D(to)
|
let delta = from.distTo2D(to)
|
||||||
arcQ.xSum = arcQ.center.reduce( (t, v) => t + v.x , 0 );
|
arcQ.xSum = arcQ.center.reduce((t, v) => t + v.x, 0);
|
||||||
arcQ.ySum = arcQ.center.reduce( (t, v) => t + v.y , 0 );
|
arcQ.ySum = arcQ.center.reduce((t, v) => t + v.y, 0);
|
||||||
arcQ.rSum = arcQ.center.reduce( (t, v) => t + v.r , 0 );
|
arcQ.rSum = arcQ.center.reduce((t, v) => t + v.r, 0);
|
||||||
let cl = arcQ.center.length;
|
let cl = arcQ.center.length;
|
||||||
let center = newPoint(
|
let center = newPoint(
|
||||||
arcQ.xSum / cl,
|
arcQ.xSum / cl,
|
||||||
|
|
@ -920,32 +913,30 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
)
|
)
|
||||||
|
|
||||||
// console.log("draining")
|
// console.log("draining")
|
||||||
|
if (arcQ.length == poly.points.length) {
|
||||||
if(arcQ.length == poly.points.length ){
|
|
||||||
//if is a circle
|
//if is a circle
|
||||||
// generate circle
|
// generate circle
|
||||||
// console.log("circle",{from, to,center});
|
// console.log("circle",{from, to,center});
|
||||||
let arcPoints = arcToPath( from, from, arcPreviewRes,{ clockwise,center})
|
let arcPoints = arcToPath(from, from, arcPreviewRes, { clockwise, center })
|
||||||
.map(applyWidgetMovement);
|
.map(applyWidgetMovement);
|
||||||
camOut(from,1);
|
camOut(from, 1);
|
||||||
camOut(from,gc,{ center:center.sub(from), clockwise, arcPoints});
|
camOut(from, gc, { center: center.sub(from), clockwise, arcPoints });
|
||||||
// lastPoint = to.clone();
|
// lastPoint = to.clone();
|
||||||
}else{
|
} else {
|
||||||
//if a non-circle arc
|
//if a non-circle arc
|
||||||
let arcPoints = arcToPath( from, to, arcPreviewRes,{ clockwise,center})
|
let arcPoints = arcToPath(from, to, arcPreviewRes, { clockwise, center })
|
||||||
.map(applyWidgetMovement);
|
.map(applyWidgetMovement);
|
||||||
// console.log("arc")
|
// console.log("arc")
|
||||||
// first arc point
|
// first arc point
|
||||||
camOut(from,1);
|
camOut(from, 1);
|
||||||
// rest of arc to final point
|
// rest of arc to final point
|
||||||
camOut(to,gc,{ center:center.sub(from), clockwise, arcPoints});
|
camOut(to, gc, { center: center.sub(from), clockwise, arcPoints });
|
||||||
lastPoint = to.clone();
|
lastPoint = to.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//if q too short, emit as lines
|
//if q too short, emit as lines
|
||||||
for (let rec of arcQ) {
|
for (let rec of arcQ) {
|
||||||
camOut(rec,1);
|
camOut(rec, 1);
|
||||||
}
|
}
|
||||||
lastPoint = arcQ.peek().clone();
|
lastPoint = arcQ.peek().clone();
|
||||||
}
|
}
|
||||||
|
|
@ -953,7 +944,10 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
arcQ.center = undefined;
|
arcQ.center = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// newLayer();
|
if (depthFirst) {
|
||||||
|
newLayer();
|
||||||
|
}
|
||||||
|
|
||||||
return lastPoint;
|
return lastPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -995,7 +989,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
|
|
||||||
function depthOutlinePath(start, depth, levels, radius, emitter, dir, ease) {
|
function depthOutlinePath(start, depth, levels, radius, emitter, dir, ease) {
|
||||||
let bottm = depth < levels.length - 1 ? levels[levels.length - 1] : null;
|
let bottm = depth < levels.length - 1 ? levels[levels.length - 1] : null;
|
||||||
let above = levels[depth-1];
|
let above = levels[depth - 1];
|
||||||
let level = levels[depth];
|
let level = levels[depth];
|
||||||
if (!level) {
|
if (!level) {
|
||||||
return start;
|
return start;
|
||||||
|
|
@ -1061,7 +1055,7 @@ function getZClearPath(terrain, x1, y1, x2, y2, z, zadd, off, over) {
|
||||||
}
|
}
|
||||||
let maxz = z;
|
let maxz = z;
|
||||||
let check = [];
|
let check = [];
|
||||||
for (let i=0; i<terrain.length; i++) {
|
for (let i = 0; i < terrain.length; i++) {
|
||||||
let data = terrain[i];
|
let data = terrain[i];
|
||||||
check.push(data);
|
check.push(data);
|
||||||
if (data.z + zadd < z) {
|
if (data.z + zadd < z) {
|
||||||
|
|
@ -1069,7 +1063,7 @@ function getZClearPath(terrain, x1, y1, x2, y2, z, zadd, off, over) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
check.reverse();
|
check.reverse();
|
||||||
for (let i=0; i<check.length; i++) {
|
for (let i = 0; i < check.length; i++) {
|
||||||
let data = check[i];
|
let data = check[i];
|
||||||
let p1 = newPoint(x1, y1);
|
let p1 = newPoint(x1, y1);
|
||||||
let p2 = newPoint(x2, y2);
|
let p2 = newPoint(x2, y2);
|
||||||
|
|
|
||||||
|
|
@ -93,15 +93,15 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
if (tabs) {
|
if (tabs) {
|
||||||
// make tab polygons
|
// make tab polygons
|
||||||
tabs.forEach(tab => {
|
tabs.forEach(tab => {
|
||||||
let zero = newPoint(0,0,0),
|
let zero = newPoint(0, 0, 0),
|
||||||
point = newPoint(tab.pos.x, tab.pos.y, tab.pos.z),
|
point = newPoint(tab.pos.x, tab.pos.y, tab.pos.z),
|
||||||
poly = newPolygon().centerRectangle(zero, tab.dim.x, tab.dim.y),
|
poly = newPolygon().centerRectangle(zero, tab.dim.x, tab.dim.y),
|
||||||
[ rx, ry, rz, rw ] = tab.rot,
|
[rx, ry, rz, rw] = tab.rot,
|
||||||
m4 = new THREE.Matrix4().makeRotationFromQuaternion(
|
m4 = new THREE.Matrix4().makeRotationFromQuaternion(
|
||||||
new THREE.Quaternion(rx, ry, rz, rw)
|
new THREE.Quaternion(rx, ry, rz, rw)
|
||||||
);
|
);
|
||||||
poly.points = poly.points
|
poly.points = poly.points
|
||||||
.map(p => new THREE.Vector3(p.x,p.y,p.z).applyMatrix4(m4))
|
.map(p => new THREE.Vector3(p.x, p.y, p.z).applyMatrix4(m4))
|
||||||
.map(v => newPoint(v.x, v.y, v.z));
|
.map(v => newPoint(v.x, v.y, v.z));
|
||||||
poly.move(point);
|
poly.move(point);
|
||||||
tab.poly = poly;
|
tab.poly = poly;
|
||||||
|
|
@ -141,7 +141,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zMin >= bounds.max.z) {
|
if (zMin >= bounds.max.z) {
|
||||||
return error(`invalid z bottom ${(zMin/units).round(3)} >= bounds z max ${(zMax/units).round(3)}`);
|
return error(`invalid z bottom ${(zMin / units).round(3)} >= bounds z max ${(zMax / units).round(3)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mark = Date.now();
|
let mark = Date.now();
|
||||||
|
|
@ -246,7 +246,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
|
|
||||||
function addSlices(slices, addIndexing = isIndexed) {
|
function addSlices(slices, addIndexing = isIndexed) {
|
||||||
if (!Array.isArray(slices)) {
|
if (!Array.isArray(slices)) {
|
||||||
slices = [ slices ];
|
slices = [slices];
|
||||||
}
|
}
|
||||||
sliceAll.appendAll(slices);
|
sliceAll.appendAll(slices);
|
||||||
if (addIndexing && axisIndex !== undefined) {
|
if (addIndexing && axisIndex !== undefined) {
|
||||||
|
|
@ -333,7 +333,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
if (tabs) {
|
if (tabs) {
|
||||||
state.terrain.forEach(slab => {
|
state.terrain.forEach(slab => {
|
||||||
tabs.forEach(tab => {
|
tabs.forEach(tab => {
|
||||||
if (tab.pos.z + tab.dim.z/2 >= slab.z) {
|
if (tab.pos.z + tab.dim.z / 2 >= slab.z) {
|
||||||
let all = [...slab.tops, tab.poly];
|
let all = [...slab.tops, tab.poly];
|
||||||
slab.tops = POLY.union(all, 0, true);
|
slab.tops = POLY.union(all, 0, true);
|
||||||
// slab.slice.output()
|
// slab.slice.output()
|
||||||
|
|
@ -348,7 +348,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
let tabpoly = tabs ? tabs.map(tab => tab.poly) : [];
|
let tabpoly = tabs ? tabs.map(tab => tab.poly) : [];
|
||||||
let allpoly = POLY.union([...state.shadow.base, ...tabpoly], 0, true);
|
let allpoly = POLY.union([...state.shadow.base, ...tabpoly], 0, true);
|
||||||
let shadowOff = maxToolDiam < 0 ? allpoly :
|
let shadowOff = maxToolDiam < 0 ? allpoly :
|
||||||
POLY.offset(allpoly, [minToolDiam/2,maxToolDiam/2], { count: 2, flat: true, minArea: 0 });
|
POLY.offset(allpoly, [minToolDiam / 2, maxToolDiam / 2], { count: 2, flat: true, minArea: 0 });
|
||||||
state.terrain.forEach(level => level.tops.appendAll(shadowOff));
|
state.terrain.forEach(level => level.tops.appendAll(shadowOff));
|
||||||
|
|
||||||
widget.terrain = state.skipTerrain ? null : state.terrain;
|
widget.terrain = state.skipTerrain ? null : state.terrain;
|
||||||
|
|
@ -369,8 +369,8 @@ export function addDogbones(poly, dist, reverse) {
|
||||||
let lastpt = oldpts[oldpts.length - 1];
|
let lastpt = oldpts[oldpts.length - 1];
|
||||||
let lastsl = lastpt.slopeTo(oldpts[0]).toUnit();
|
let lastsl = lastpt.slopeTo(oldpts[0]).toUnit();
|
||||||
let length = oldpts.length + (open ? 0 : 1);
|
let length = oldpts.length + (open ? 0 : 1);
|
||||||
let newpts = [ ];
|
let newpts = [];
|
||||||
for (let i=0; i<length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
let nextpt = oldpts[i % oldpts.length];
|
let nextpt = oldpts[i % oldpts.length];
|
||||||
let nextsl = lastpt.slopeTo(nextpt).toUnit();
|
let nextsl = lastpt.slopeTo(nextpt).toUnit();
|
||||||
let adiff = lastsl.angleDiff(nextsl, true);
|
let adiff = lastsl.angleDiff(nextsl, true);
|
||||||
|
|
@ -409,8 +409,8 @@ export async function traces(settings, widget, single) {
|
||||||
let pcache = {};
|
let pcache = {};
|
||||||
let points = new Array(2);
|
let points = new Array(2);
|
||||||
let lines = new Array(points.length / 2);
|
let lines = new Array(points.length / 2);
|
||||||
for (let i=0, j=0, k=0, l=array.length; i<l; ) {
|
for (let i = 0, j = 0, k = 0, l = array.length; i < l;) {
|
||||||
let ps = [ array[i++], array[i++], array[i++] ];
|
let ps = [array[i++], array[i++], array[i++]];
|
||||||
let key = ps.map(v => (v * 10000) | 0).join(',');
|
let key = ps.map(v => (v * 10000) | 0).join(',');
|
||||||
let point = pcache[key];
|
let point = pcache[key];
|
||||||
if (!point) {
|
if (!point) {
|
||||||
|
|
@ -420,7 +420,7 @@ export async function traces(settings, widget, single) {
|
||||||
}
|
}
|
||||||
points[j++ % 2] = point;
|
points[j++ % 2] = point;
|
||||||
if (j % 2 === 0) {
|
if (j % 2 === 0) {
|
||||||
let [ p0, p1 ] = points;
|
let [p0, p1] = points;
|
||||||
let line = lines[k++] = newLine(p0, p1);
|
let line = lines[k++] = newLine(p0, p1);
|
||||||
p0.lines.push(line);
|
p0.lines.push(line);
|
||||||
p1.lines.push(line);
|
p1.lines.push(line);
|
||||||
|
|
@ -513,10 +513,10 @@ export async function traces(settings, widget, single) {
|
||||||
* @param {Function} onProgress - callback function to report progress
|
* @param {Function} onProgress - callback function to report progress
|
||||||
* @returns {Array} list of hole centers as objects with `x`, `y`, `z`, `depth`, and `selected` properties.
|
* @returns {Array} list of hole centers as objects with `x`, `y`, `z`, `depth`, and `selected` properties.
|
||||||
*/
|
*/
|
||||||
export async function holes(settings, widget, individual, rec,onProgress) {
|
export async function holes(settings, widget, individual, rec, onProgress) {
|
||||||
|
|
||||||
let {tool,mark,precision} = rec //TODO: display some visual difference if mark is selected
|
let { tool, mark, precision } = rec //TODO: display some visual difference if mark is selected
|
||||||
let toolDiam = new Tool(settings,tool).fluteDiameter()
|
let toolDiam = new Tool(settings, tool).fluteDiameter()
|
||||||
let diam = individual ? 1 : toolDiam; // sets default diameter when select individual used
|
let diam = individual ? 1 : toolDiam; // sets default diameter when select individual used
|
||||||
|
|
||||||
let proc = settings.process,
|
let proc = settings.process,
|
||||||
|
|
@ -535,11 +535,11 @@ export async function holes(settings, widget, individual, rec,onProgress) {
|
||||||
zBottom = isIndexed ? camZBottom : camZBottom - zbOff;
|
zBottom = isIndexed ? camZBottom : camZBottom - zbOff;
|
||||||
|
|
||||||
|
|
||||||
let slicerOpts = {flatoff: 0.001}
|
let slicerOpts = { flatoff: 0.001 }
|
||||||
let slicer = new cam_slicer(widget,slicerOpts);
|
let slicer = new cam_slicer(widget, slicerOpts);
|
||||||
let zFlats = Object.keys(slicer.zFlat).map(Number).map(z=>[z,z-0.002]).flat()
|
let zFlats = Object.keys(slicer.zFlat).map(Number).map(z => [z, z - 0.002]).flat()
|
||||||
|
|
||||||
precision = Math.max( 0, precision )
|
precision = Math.max(0, precision)
|
||||||
let intervals = (precision == 0) ? [] : slicer.interval(
|
let intervals = (precision == 0) ? [] : slicer.interval(
|
||||||
precision,
|
precision,
|
||||||
{
|
{
|
||||||
|
|
@ -547,25 +547,25 @@ export async function holes(settings, widget, individual, rec,onProgress) {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
let zees = [...zFlats,...intervals]
|
let zees = [...zFlats, ...intervals]
|
||||||
let indices = [...new Set(zees
|
let indices = [...new Set(zees
|
||||||
.map(kv => parseFloat(kv).round(5))
|
.map(kv => parseFloat(kv).round(5))
|
||||||
.filter(z => z !== null)
|
.filter(z => z !== null)
|
||||||
)]
|
)]
|
||||||
let centerDiff = diam * 0.1,
|
let centerDiff = diam * 0.1,
|
||||||
area = (diam/2) * (diam/2) * Math.PI,
|
area = (diam / 2) * (diam / 2) * Math.PI,
|
||||||
circles = [],
|
circles = [],
|
||||||
slices = [];
|
slices = [];
|
||||||
|
|
||||||
function onEach(slice) {
|
function onEach(slice) {
|
||||||
slices.push(slice);
|
slices.push(slice);
|
||||||
}
|
}
|
||||||
let opts = { each: onEach, progress: (num,total)=> onProgress(num/total*0.5,"slice") };
|
let opts = { each: onEach, progress: (num, total) => onProgress(num / total * 0.5, "slice") };
|
||||||
await slicer.slice(indices, opts);
|
await slicer.slice(indices, opts);
|
||||||
let shadowedDrills = false;
|
let shadowedDrills = false;
|
||||||
// console.log("slices",slices)
|
// console.log("slices",slices)
|
||||||
for (let [i,slice] of slices.entries()) {
|
for (let [i, slice] of slices.entries()) {
|
||||||
for(let top of slice.tops){
|
for (let top of slice.tops) {
|
||||||
// console.log("slicing",slice.z,top)
|
// console.log("slicing",slice.z,top)
|
||||||
slice.shadow = computeShadowAt(widget, slice.z, 0)
|
slice.shadow = computeShadowAt(widget, slice.z, 0)
|
||||||
let inner = top.inner;
|
let inner = top.inner;
|
||||||
|
|
@ -573,13 +573,13 @@ export async function holes(settings, widget, individual, rec,onProgress) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (let poly of inner) {
|
for (let poly of inner) {
|
||||||
if ( poly.points.length < 7 ) continue;
|
if (poly.points.length < 7) continue;
|
||||||
let center = poly.calcCircleCenter();
|
let center = poly.calcCircleCenter();
|
||||||
center.area = poly.area();
|
center.area = poly.area();
|
||||||
center.overlapping = [center]
|
center.overlapping = [center]
|
||||||
center.depth = 0;
|
center.depth = 0;
|
||||||
// console.log("center",center)
|
// console.log("center",center)
|
||||||
if ( poly.circularity() < 0.985 ){
|
if (poly.circularity() < 0.985) {
|
||||||
// if not circular, don't add to holes
|
// if not circular, don't add to holes
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -589,11 +589,11 @@ export async function holes(settings, widget, individual, rec,onProgress) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let overlap = false;
|
let overlap = false;
|
||||||
for (let [i,circle] of circles.entries()) {
|
for (let [i, circle] of circles.entries()) {
|
||||||
let dist = circle.distTo2D(center)
|
let dist = circle.distTo2D(center)
|
||||||
|
|
||||||
// //if on the same xy point,
|
// //if on the same xy point,
|
||||||
if (dist <= centerDiff ) {
|
if (dist <= centerDiff) {
|
||||||
// console.log("overlap",center,circle);
|
// console.log("overlap",center,circle);
|
||||||
circle.overlapping.push(center);
|
circle.overlapping.push(center);
|
||||||
// if overlapping, don't add and continue
|
// if overlapping, don't add and continue
|
||||||
|
|
@ -604,40 +604,40 @@ export async function holes(settings, widget, individual, rec,onProgress) {
|
||||||
if (!overlap) circles.push(center);
|
if (!overlap) circles.push(center);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onProgress(0.5+(i/slices.length*0.25),"recognize circles")
|
onProgress(0.5 + (i / slices.length * 0.25), "recognize circles")
|
||||||
}
|
}
|
||||||
|
|
||||||
let drills = []
|
let drills = []
|
||||||
|
|
||||||
for (let [i,c] of circles.entries()) {
|
for (let [i, c] of circles.entries()) {
|
||||||
let overlapping = c.overlapping
|
let overlapping = c.overlapping
|
||||||
|
|
||||||
let last = overlapping.shift();
|
let last = overlapping.shift();
|
||||||
while (overlapping.length) {
|
while (overlapping.length) {
|
||||||
let circ = overlapping.shift();
|
let circ = overlapping.shift();
|
||||||
let aveArea = (circ.area + last.area) / 2;
|
let aveArea = (circ.area + last.area) / 2;
|
||||||
let areaDelta = Math.abs(circ.area -last.area)
|
let areaDelta = Math.abs(circ.area - last.area)
|
||||||
if (areaDelta < aveArea * 0.05){ // if area delta less than 5% of average area
|
if (areaDelta < aveArea * 0.05) { // if area delta less than 5% of average area
|
||||||
//keep top circle selected
|
//keep top circle selected
|
||||||
last.depth = last.z - circ.z;
|
last.depth = last.z - circ.z;
|
||||||
}else{ // if not the same area
|
} else { // if not the same area
|
||||||
//push and move on
|
//push and move on
|
||||||
drills.push(last);
|
drills.push(last);
|
||||||
last = circ;
|
last = circ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (last.depth != 0) drills.push(last) //add last circle
|
if (last.depth != 0) drills.push(last) //add last circle
|
||||||
onProgress(0.75+(i/circles.length*0.25),"assemble holes")
|
onProgress(0.75 + (i / circles.length * 0.25), "assemble holes")
|
||||||
}
|
}
|
||||||
drills.forEach( h=>{
|
drills.forEach(h => {
|
||||||
if(rec.fromTop){
|
if (rec.fromTop) {
|
||||||
// set z top if selected
|
// set z top if selected
|
||||||
h.depth += wztop - h.z
|
h.depth += wztop - h.z
|
||||||
h.z = wztop
|
h.z = wztop
|
||||||
}
|
}
|
||||||
delete h.overlapping //for encoding
|
delete h.overlapping //for encoding
|
||||||
h.diam = toolDiam // for mesh generation
|
h.diam = toolDiam // for mesh generation
|
||||||
h.selected = (!individual && Math.abs(h.area - area) <= area * 0.05 ); //for same size selection
|
h.selected = (!individual && Math.abs(h.area - area) <= area * 0.05); //for same size selection
|
||||||
})
|
})
|
||||||
|
|
||||||
// console.log("unfiltered circles",circles)
|
// console.log("unfiltered circles",circles)
|
||||||
|
|
@ -649,13 +649,13 @@ export async function holes(settings, widget, individual, rec,onProgress) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function cutTabs(tabs, offset, z, inter) {
|
function cutTabs(tabs, offset, z, inter) {
|
||||||
tabs = tabs.filter(tab => z < tab.pos.z + tab.dim.z/2).map(tab => tab.off).flat();
|
tabs = tabs.filter(tab => z < tab.pos.z + tab.dim.z / 2).map(tab => tab.off).flat();
|
||||||
return cutPolys(tabs, offset, z, false);
|
return cutPolys(tabs, offset, z, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cutPolys(polys, offset, z, inter) {
|
function cutPolys(polys, offset, z, inter) {
|
||||||
let noff = [];
|
let noff = [];
|
||||||
offset.forEach(op => noff.appendAll( op.cut(POLY.union(polys, 0, true), inter) ));
|
offset.forEach(op => noff.appendAll(op.cut(POLY.union(polys, 0, true), inter)));
|
||||||
return healPolys(noff);
|
return healPolys(noff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -682,12 +682,12 @@ function healPolys(noff) {
|
||||||
if (noff.length > 1) {
|
if (noff.length > 1) {
|
||||||
let heal = 0;
|
let heal = 0;
|
||||||
// heal/rejoin open segments that share endpoints
|
// heal/rejoin open segments that share endpoints
|
||||||
outer: for(;; heal++) {
|
outer: for (; ; heal++) {
|
||||||
let ntmp = noff, tlen = ntmp.length;
|
let ntmp = noff, tlen = ntmp.length;
|
||||||
for (let i=0; i<tlen; i++) {
|
for (let i = 0; i < tlen; i++) {
|
||||||
let s1 = ntmp[i];
|
let s1 = ntmp[i];
|
||||||
if (!s1) continue;
|
if (!s1) continue;
|
||||||
for (let j=i+1; j<tlen; j++) {
|
for (let j = i + 1; j < tlen; j++) {
|
||||||
let s2 = ntmp[j];
|
let s2 = ntmp[j];
|
||||||
if (!s2) continue;
|
if (!s2) continue;
|
||||||
// require polys at same Z to heal
|
// require polys at same Z to heal
|
||||||
|
|
@ -743,13 +743,13 @@ export function computeShadowAt(widget, z, ztop) {
|
||||||
// cache faces with normals up
|
// cache faces with normals up
|
||||||
if (!widget.cache.shadow) {
|
if (!widget.cache.shadow) {
|
||||||
const faces = [];
|
const faces = [];
|
||||||
for (let i=0, ip=0; i<length; i += 3) {
|
for (let i = 0, ip = 0; i < length; i += 3) {
|
||||||
const a = new THREE.Vector3(geo[ip++], geo[ip++], geo[ip++]);
|
const a = new THREE.Vector3(geo[ip++], geo[ip++], geo[ip++]);
|
||||||
const b = new THREE.Vector3(geo[ip++], geo[ip++], geo[ip++]);
|
const b = new THREE.Vector3(geo[ip++], geo[ip++], geo[ip++]);
|
||||||
const c = new THREE.Vector3(geo[ip++], geo[ip++], geo[ip++]);
|
const c = new THREE.Vector3(geo[ip++], geo[ip++], geo[ip++]);
|
||||||
const n = THREE.computeFaceNormal(a,b,c);
|
const n = THREE.computeFaceNormal(a, b, c);
|
||||||
if (n.z > 0.001) {
|
if (n.z > 0.001) {
|
||||||
faces.push(a,b,c);
|
faces.push(a, b, c);
|
||||||
// faces.push(newPoint(...a), newPoint(...b), newPoint(...c));
|
// faces.push(newPoint(...a), newPoint(...b), newPoint(...c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -758,7 +758,7 @@ export function computeShadowAt(widget, z, ztop) {
|
||||||
const found = [];
|
const found = [];
|
||||||
const faces = widget.cache.shadow;
|
const faces = widget.cache.shadow;
|
||||||
const { checkOverUnderOn, intersectPoints } = cam_slicer;
|
const { checkOverUnderOn, intersectPoints } = cam_slicer;
|
||||||
for (let i=0; i<faces.length; ) {
|
for (let i = 0; i < faces.length;) {
|
||||||
const a = faces[i++];
|
const a = faces[i++];
|
||||||
const b = faces[i++];
|
const b = faces[i++];
|
||||||
const c = faces[i++];
|
const c = faces[i++];
|
||||||
|
|
@ -771,7 +771,7 @@ export function computeShadowAt(widget, z, ztop) {
|
||||||
// skip faces under threshold
|
// skip faces under threshold
|
||||||
continue;
|
continue;
|
||||||
} else if (a.z > z && b.z > z && c.z > z) {
|
} else if (a.z > z && b.z > z && c.z > z) {
|
||||||
found.push([a,b,c]);
|
found.push([a, b, c]);
|
||||||
} else {
|
} else {
|
||||||
// check faces straddling threshold
|
// check faces straddling threshold
|
||||||
const where = { under: [], over: [], on: [] };
|
const where = { under: [], over: [], on: [] };
|
||||||
|
|
@ -789,7 +789,7 @@ export function computeShadowAt(widget, z, ztop) {
|
||||||
found.push([where.over[0], line[0], line[1]]);
|
found.push([where.over[0], line[0], line[1]]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log({msg: "invalid ips", line: line, where: where});
|
console.log({ msg: "invalid ips", line: line, where: where });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -797,9 +797,9 @@ export function computeShadowAt(widget, z, ztop) {
|
||||||
|
|
||||||
let polys = found.map(a => {
|
let polys = found.map(a => {
|
||||||
return newPolygon()
|
return newPolygon()
|
||||||
.add(a[0].x,a[0].y,a[0].z)
|
.add(a[0].x, a[0].y, a[0].z)
|
||||||
.add(a[1].x,a[1].y,a[1].z)
|
.add(a[1].x, a[1].y, a[1].z)
|
||||||
.add(a[2].x,a[2].y,a[2].z);
|
.add(a[2].x, a[2].y, a[2].z);
|
||||||
});
|
});
|
||||||
|
|
||||||
polys = POLY.union(polys, 0.001, true);
|
polys = POLY.union(polys, 0.001, true);
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,11 @@ const { sliceConnect, sliceDedup } = slicer;
|
||||||
const { config } = base;
|
const { config } = base;
|
||||||
const timing = false;
|
const timing = false;
|
||||||
|
|
||||||
const begin = function() {
|
const begin = function () {
|
||||||
if (timing) console.time(...arguments);
|
if (timing) console.time(...arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
const end = function() {
|
const end = function () {
|
||||||
if (timing) console.timeEnd(...arguments);
|
if (timing) console.timeEnd(...arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -74,15 +74,15 @@ export class Slicer {
|
||||||
zList[z] = (zList[z] || 0) + 1;
|
zList[z] = (zList[z] || 0) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let p1 = newPoint(0,0,0),
|
let p1 = newPoint(0, 0, 0),
|
||||||
p2 = newPoint(0,0,0),
|
p2 = newPoint(0, 0, 0),
|
||||||
p3 = newPoint(0,0,0);
|
p3 = newPoint(0, 0, 0);
|
||||||
|
|
||||||
// for (let i = 0, il = points.length; i < il; i++) {
|
// for (let i = 0, il = points.length; i < il; i++) {
|
||||||
// points[i] = points[i].round(5);
|
// points[i] = points[i].round(5);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
for (let i = 0, il = points.length; i < il; ) {
|
for (let i = 0, il = points.length; i < il;) {
|
||||||
p1.set(points[i++], points[i++], points[i++]);
|
p1.set(points[i++], points[i++], points[i++]);
|
||||||
p2.set(points[i++], points[i++], points[i++]);
|
p2.set(points[i++], points[i++], points[i++]);
|
||||||
p3.set(points[i++], points[i++], points[i++]);
|
p3.set(points[i++], points[i++], points[i++]);
|
||||||
|
|
@ -100,7 +100,7 @@ export class Slicer {
|
||||||
if (p1.z === p2.z && p2.z === p3.z) {
|
if (p1.z === p2.z && p2.z === p3.z) {
|
||||||
// detect zFlat faces to avoid slicing directly on them
|
// detect zFlat faces to avoid slicing directly on them
|
||||||
let zkey = p1.z.toFixed(5),
|
let zkey = p1.z.toFixed(5),
|
||||||
area = Math.abs(util.area2(p1,p2,p3)) / 2;
|
area = Math.abs(util.area2(p1, p2, p3)) / 2;
|
||||||
if (!zFlat[zkey]) {
|
if (!zFlat[zkey]) {
|
||||||
zFlat[zkey] = area;
|
zFlat[zkey] = area;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -155,7 +155,7 @@ export class Slicer {
|
||||||
|
|
||||||
// sort Z and offset when on a flat
|
// sort Z and offset when on a flat
|
||||||
const flatoff = util.numOrDefault(opt.flatoff, 0.01);
|
const flatoff = util.numOrDefault(opt.flatoff, 0.01);
|
||||||
zs = zs.sort((a,b) => a-b).map(z => {
|
zs = zs.sort((a, b) => a - b).map(z => {
|
||||||
if (!flatoff) {
|
if (!flatoff) {
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
@ -183,13 +183,13 @@ export class Slicer {
|
||||||
b += step;
|
b += step;
|
||||||
}
|
}
|
||||||
|
|
||||||
let p1 = newPoint(0,0,0),
|
let p1 = newPoint(0, 0, 0),
|
||||||
p2 = newPoint(0,0,0),
|
p2 = newPoint(0, 0, 0),
|
||||||
p3 = newPoint(0,0,0),
|
p3 = newPoint(0, 0, 0),
|
||||||
ep = 0.001;
|
ep = 0.001;
|
||||||
|
|
||||||
begin("create buckets");
|
begin("create buckets");
|
||||||
for (let i = 0, il = points.length; i < il; ) {
|
for (let i = 0, il = points.length; i < il;) {
|
||||||
p1.set(points[i++], points[i++], points[i++]);
|
p1.set(points[i++], points[i++], points[i++]);
|
||||||
p2.set(points[i++], points[i++], points[i++]);
|
p2.set(points[i++], points[i++], points[i++]);
|
||||||
p3.set(points[i++], points[i++], points[i++]);
|
p3.set(points[i++], points[i++], points[i++]);
|
||||||
|
|
@ -236,7 +236,7 @@ export class Slicer {
|
||||||
}
|
}
|
||||||
const data = (await Promise.all(promises)).flat();
|
const data = (await Promise.all(promises)).flat();
|
||||||
|
|
||||||
data.sort((a,b) => b.z - a.z).forEach((rec, i) => {
|
data.sort((a, b) => b.z - a.z).forEach((rec, i) => {
|
||||||
rec.tops = rec.polys;
|
rec.tops = rec.polys;
|
||||||
rec.slice = newSlice(rec.z).addTops(rec.tops);
|
rec.slice = newSlice(rec.z).addTops(rec.tops);
|
||||||
if (opt.each) {
|
if (opt.each) {
|
||||||
|
|
@ -297,16 +297,16 @@ export class Slicer {
|
||||||
|
|
||||||
// const { points } = this,
|
// const { points } = this,
|
||||||
const points = indices,
|
const points = indices,
|
||||||
p1 = newPoint(0,0,0),
|
p1 = newPoint(0, 0, 0),
|
||||||
p2 = newPoint(0,0,0),
|
p2 = newPoint(0, 0, 0),
|
||||||
p3 = newPoint(0,0,0);
|
p3 = newPoint(0, 0, 0);
|
||||||
|
|
||||||
for (let index = 0; index < points.length; ) {
|
for (let index = 0; index < points.length;) {
|
||||||
p1.set(points[index++], points[index++], points[index++]);
|
p1.set(points[index++], points[index++], points[index++]);
|
||||||
p2.set(points[index++], points[index++], points[index++]);
|
p2.set(points[index++], points[index++], points[index++]);
|
||||||
p3.set(points[index++], points[index++], points[index++]);
|
p3.set(points[index++], points[index++], points[index++]);
|
||||||
|
|
||||||
let where = {under: [], over: [], on: []};
|
let where = { under: [], over: [], on: [] };
|
||||||
checkOverUnderOn(p1, z, where);
|
checkOverUnderOn(p1, z, where);
|
||||||
checkOverUnderOn(p2, z, where);
|
checkOverUnderOn(p2, z, where);
|
||||||
checkOverUnderOn(p3, z, where);
|
checkOverUnderOn(p3, z, where);
|
||||||
|
|
@ -334,7 +334,7 @@ export class Slicer {
|
||||||
if (line.length === 2) {
|
if (line.length === 2) {
|
||||||
lines.push(makeZLine(phash, line[0], line[1]));
|
lines.push(makeZLine(phash, line[0], line[1]));
|
||||||
} else {
|
} else {
|
||||||
console.log({msg: "invalid ips", line: line, where: where});
|
console.log({ msg: "invalid ips", line: line, where: where });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -344,7 +344,8 @@ export class Slicer {
|
||||||
lines = sliceDedup(lines, debug);
|
lines = sliceDedup(lines, debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
return lines.length ? { z,
|
return lines.length ? {
|
||||||
|
z,
|
||||||
lines: opt.lines !== false ? lines : undefined,
|
lines: opt.lines !== false ? lines : undefined,
|
||||||
polys: links ? POLY.nest(sliceConnect(lines, opt, debug)) : undefined
|
polys: links ? POLY.nest(sliceConnect(lines, opt, debug)) : undefined
|
||||||
} : null;
|
} : null;
|
||||||
|
|
@ -367,12 +368,12 @@ export class Slicer {
|
||||||
step = (zmax - zmin) / count;
|
step = (zmax - zmin) / count;
|
||||||
}
|
}
|
||||||
if (opt.down) {
|
if (opt.down) {
|
||||||
for (let i=0; i<count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
array.push(zmax);
|
array.push(zmax);
|
||||||
zmax -= step;
|
zmax -= step;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (let i=0; i<count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
array.push(zmin);
|
array.push(zmin);
|
||||||
zmin += step;
|
zmin += step;
|
||||||
}
|
}
|
||||||
|
|
@ -392,13 +393,13 @@ export class Slicer {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// add over and under all flats by 'off'
|
// add over and under all flats by 'off'
|
||||||
array.appendAll(add).sort((a,b) => {
|
array.appendAll(add).sort((a, b) => {
|
||||||
return opt.down ? b-a : a-b;
|
return opt.down ? b - a : a - b;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter duplicate values
|
// filter duplicate values
|
||||||
array = array.map(v => v.round(5)).filter((e,i,a) => i < 1 || a[i-1] !== a[i]);
|
array = array.map(v => v.round(5)).filter((e, i, a) => i < 1 || a[i - 1] !== a[i]);
|
||||||
|
|
||||||
// return array.map(v => Math.abs(parseFloat(v.toFixed(5))));
|
// return array.map(v => Math.abs(parseFloat(v.toFixed(5))));
|
||||||
return array.map(v => parseFloat(v.toFixed(5)));
|
return array.map(v => parseFloat(v.toFixed(5)));
|
||||||
|
|
@ -471,7 +472,7 @@ function getCachedPoint(phash, p) {
|
||||||
function makeZLine(phash, p1, p2, coplanar, edge) {
|
function makeZLine(phash, p1, p2, coplanar, edge) {
|
||||||
p1 = getCachedPoint(phash, p1.clone());
|
p1 = getCachedPoint(phash, p1.clone());
|
||||||
p2 = getCachedPoint(phash, p2.clone());
|
p2 = getCachedPoint(phash, p2.clone());
|
||||||
let line = newOrderedLine(p1,p2);
|
let line = newOrderedLine(p1, p2);
|
||||||
line.coplanar = coplanar || false;
|
line.coplanar = coplanar || false;
|
||||||
line.edge = edge || false;
|
line.edge = edge || false;
|
||||||
return line;
|
return line;
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,10 @@ function prepareSlices(callback, scale = 1, offset = 0) {
|
||||||
if (msg && msg !== lastMsg) {
|
if (msg && msg !== lastMsg) {
|
||||||
let mark = Date.now();
|
let mark = Date.now();
|
||||||
if (lastMsg) {
|
if (lastMsg) {
|
||||||
segtimes[`${widget.id}_${segNumber++}_${lastMsg}`] = mark - startTime;
|
let key = widgets.length > 1 ?
|
||||||
|
`${widget.id}_${segNumber++}_${lastMsg}` :
|
||||||
|
`${segNumber++}_${lastMsg}`
|
||||||
|
segtimes[key] = mark - startTime;
|
||||||
}
|
}
|
||||||
lastMsg = msg;
|
lastMsg = msg;
|
||||||
startTime = mark;
|
startTime = mark;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue