add shadow docs, add ztop limit to pocket and trace
This commit is contained in:
parent
a6675efbb4
commit
a48b0f1d80
7 changed files with 138 additions and 41 deletions
|
|
@ -160,6 +160,12 @@ function inRange(value, min, max) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function round(v, zeros) {
|
function round(v, zeros) {
|
||||||
|
if (typeof v === 'object') {
|
||||||
|
for (let [key,val] of Object.entries(v)) {
|
||||||
|
v[key] = round(val);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
const prec = zeros !== undefined ? zeros : round_decimal_precision;
|
const prec = zeros !== undefined ? zeros : round_decimal_precision;
|
||||||
if (prec === 0) return v | 0;
|
if (prec === 0) return v | 0;
|
||||||
let pow = Math.pow(10, prec);
|
let pow = Math.pow(10, prec);
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ let isAnimate,
|
||||||
isIndexed,
|
isIndexed,
|
||||||
isParsed,
|
isParsed,
|
||||||
camStock,
|
camStock,
|
||||||
|
camZTop,
|
||||||
camZBottom,
|
camZBottom,
|
||||||
current,
|
current,
|
||||||
currentIndex,
|
currentIndex,
|
||||||
|
|
@ -1281,6 +1282,10 @@ CAM.init = function(kiri, api) {
|
||||||
return current.device.spindleMax > 0;
|
return current.device.spindleMax > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function zTop() {
|
||||||
|
return API.conf.get().process.camZTop > 0;
|
||||||
|
}
|
||||||
|
|
||||||
function zBottom() {
|
function zBottom() {
|
||||||
return API.conf.get().process.camZBottom > 0;
|
return API.conf.get().process.camZBottom > 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1318,7 +1323,6 @@ CAM.init = function(kiri, api) {
|
||||||
voids: 'camRoughVoid',
|
voids: 'camRoughVoid',
|
||||||
flats: 'camRoughFlat',
|
flats: 'camRoughFlat',
|
||||||
inside: 'camRoughIn',
|
inside: 'camRoughIn',
|
||||||
top: 'camRoughTop'
|
|
||||||
}).inputs = {
|
}).inputs = {
|
||||||
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
sep: UC.newBlank({class:"pop-sep"}),
|
sep: UC.newBlank({class:"pop-sep"}),
|
||||||
|
|
@ -1334,7 +1338,6 @@ CAM.init = function(kiri, api) {
|
||||||
all: UC.newBoolean(LANG.cr_clst_s, undefined, {title:LANG.cr_clst_l, show:hasIndexing}),
|
all: UC.newBoolean(LANG.cr_clst_s, undefined, {title:LANG.cr_clst_l, show:hasIndexing}),
|
||||||
voids: UC.newBoolean(LANG.cr_clrp_s, undefined, {title:LANG.cr_clrp_l}),
|
voids: UC.newBoolean(LANG.cr_clrp_s, undefined, {title:LANG.cr_clrp_l}),
|
||||||
flats: UC.newBoolean(LANG.cr_clrf_s, undefined, {title:LANG.cr_clrf_l}),
|
flats: UC.newBoolean(LANG.cr_clrf_s, undefined, {title:LANG.cr_clrf_l}),
|
||||||
top: UC.newBoolean(LANG.cr_clrt_s, undefined, {title:LANG.cr_clrt_l}),
|
|
||||||
inside: UC.newBoolean(LANG.cr_olin_s, undefined, {title:LANG.cr_olin_l})
|
inside: UC.newBoolean(LANG.cr_olin_s, undefined, {title:LANG.cr_olin_l})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1876,9 +1879,11 @@ function updateStock() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isCamMode) {
|
if (!isCamMode) {
|
||||||
|
SPACE.world.remove(camZTop);
|
||||||
SPACE.world.remove(camZBottom);
|
SPACE.world.remove(camZBottom);
|
||||||
SPACE.world.remove(camStock);
|
SPACE.world.remove(camStock);
|
||||||
camStock = null;
|
camStock = null;
|
||||||
|
camZTop = null;
|
||||||
camZBottom = null;
|
camZBottom = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1941,6 +1946,32 @@ function updateStock() {
|
||||||
camStock = null;
|
camStock = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPACE.world.remove(camZTop);
|
||||||
|
if (process.camZTop && widgets.length) {
|
||||||
|
let max = { x, y, z };
|
||||||
|
for (let w of widgets) {
|
||||||
|
max.x = Math.max(max.x, w.track.box.w);
|
||||||
|
max.y = Math.max(max.y, w.track.box.h);
|
||||||
|
max.z = Math.max(max.z, w.track.box.d);
|
||||||
|
}
|
||||||
|
let geo = new THREE.PlaneGeometry(max.x, max.y);
|
||||||
|
let mat = new THREE.MeshBasicMaterial({
|
||||||
|
color: 0x777777,
|
||||||
|
opacity: 0.55,
|
||||||
|
transparent: true,
|
||||||
|
side:THREE.DoubleSide
|
||||||
|
});
|
||||||
|
camZTop = new THREE.Mesh(geo, mat);
|
||||||
|
camZTop._max = max;
|
||||||
|
camZTop.renderOrder = 1;
|
||||||
|
camZTop.position.x = center.x;
|
||||||
|
camZTop.position.y = center.y;
|
||||||
|
camZTop.position.z = process.camZTop;
|
||||||
|
SPACE.world.add(camZTop);
|
||||||
|
} else {
|
||||||
|
camZTop = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
SPACE.world.remove(camZBottom);
|
SPACE.world.remove(camZBottom);
|
||||||
if (process.camZBottom && widgets.length) {
|
if (process.camZBottom && widgets.length) {
|
||||||
let max = { x, y, z };
|
let max = { x, y, z };
|
||||||
|
|
|
||||||
|
|
@ -171,17 +171,19 @@ class OpRough extends CamOp {
|
||||||
|
|
||||||
async slice(progress) {
|
async slice(progress) {
|
||||||
let { op, state } = this;
|
let { op, state } = this;
|
||||||
let { settings, widget, slicer, addSlices, unsafe, color } = state;
|
let { settings, slicer, addSlices, unsafe, color } = state;
|
||||||
let { updateToolDiams, thruHoles, tabs, cutTabs, cutPolys } = state;
|
let { updateToolDiams, thruHoles, tabs, cutTabs, cutPolys } = state;
|
||||||
let { tshadow, shadowTop, ztOff, zBottom, zThru, zMax, shadowAt, isIndexed } = state;
|
let { ztOff, zBottom, zThru, zMax, shadowAt, isIndexed} = state;
|
||||||
|
let { workarea } = state;
|
||||||
let { process, stock } = settings;
|
let { process, stock } = settings;
|
||||||
|
|
||||||
if (op.down <= 0) {
|
if (op.down <= 0) {
|
||||||
throw `invalid step down "${op.down}"`;
|
throw `invalid step down "${op.down}"`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log({ rough: workarea, shadow: state.shadow });
|
||||||
|
|
||||||
let roughIn = op.inside;
|
let roughIn = op.inside;
|
||||||
let roughTop = op.top;
|
|
||||||
let roughDown = op.down;
|
let roughDown = op.down;
|
||||||
let roughLeave = op.leave || 0;
|
let roughLeave = op.leave || 0;
|
||||||
let roughLeaveZ = op.leavez || 0;
|
let roughLeaveZ = op.leavez || 0;
|
||||||
|
|
@ -189,9 +191,11 @@ class OpRough extends CamOp {
|
||||||
let toolDiam = new CAM.Tool(settings, op.tool).fluteDiameter();
|
let toolDiam = new CAM.Tool(settings, op.tool).fluteDiameter();
|
||||||
let trueShadow = process.camTrueShadow === true;
|
let trueShadow = process.camTrueShadow === true;
|
||||||
|
|
||||||
// create facing slices
|
updateToolDiams(toolDiam);
|
||||||
if (roughTop) {
|
|
||||||
let shadow = tshadow.clone();
|
// clear the stock above the area to be roughed out
|
||||||
|
{
|
||||||
|
let shadow = state.shadow.base.clone();
|
||||||
let step = toolDiam * op.step;
|
let step = toolDiam * op.step;
|
||||||
let inset = roughStock ?
|
let inset = roughStock ?
|
||||||
POLY.offset([ newPolygon().centerRectangle(stock.center, stock.x, stock.y) ], step) :
|
POLY.offset([ newPolygon().centerRectangle(stock.center, stock.x, stock.y) ], step) :
|
||||||
|
|
@ -210,7 +214,7 @@ class OpRough extends CamOp {
|
||||||
let camFaces = this.camFaces = [];
|
let camFaces = this.camFaces = [];
|
||||||
let zstart = zMax + ztOff - zstep;
|
let zstart = zMax + ztOff - zstep;
|
||||||
for (let z = zstart; zsteps > 0; zsteps--) {
|
for (let z = zstart; zsteps > 0; zsteps--) {
|
||||||
let slice = shadowTop.slice.clone(false);
|
let slice = newSlice();
|
||||||
slice.z = z;
|
slice.z = z;
|
||||||
slice.camLines = POLY.setZ(facing.clone(true), slice.z + roughLeaveZ);
|
slice.camLines = POLY.setZ(facing.clone(true), slice.z + roughLeaveZ);
|
||||||
slice.output()
|
slice.output()
|
||||||
|
|
@ -223,16 +227,17 @@ class OpRough extends CamOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create roughing slices
|
// create roughing slices
|
||||||
updateToolDiams(toolDiam);
|
|
||||||
|
|
||||||
let flats = [];
|
let flats = [];
|
||||||
let shadow = [];
|
let shadow = [];
|
||||||
let slices = [];
|
let slices = [];
|
||||||
let indices = slicer.interval(roughDown, {
|
let indices = slicer.interval(roughDown, {
|
||||||
down: true, min: 0, fit: true, off: 0.01
|
down: true, min: 0, fit: true, off: 0.01
|
||||||
});
|
});
|
||||||
|
|
||||||
// shift out first (top-most) slice
|
// shift out first (top-most) slice
|
||||||
indices.shift();
|
indices.shift();
|
||||||
|
|
||||||
|
// find flats and add to indices for slicing
|
||||||
if (op.flats) {
|
if (op.flats) {
|
||||||
let flatArea = (Math.PI * (toolDiam/2) * (toolDiam/2)) / 2;
|
let flatArea = (Math.PI * (toolDiam/2) * (toolDiam/2)) / 2;
|
||||||
let flats = Object.entries(slicer.zFlat)
|
let flats = Object.entries(slicer.zFlat)
|
||||||
|
|
@ -278,11 +283,8 @@ class OpRough extends CamOp {
|
||||||
// exclude flats injected to complete shadow
|
// exclude flats injected to complete shadow
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// data.shadow = trueShadow ? CAM.shadowAt(widget, data.z) : shadow.clone(true);
|
|
||||||
data.shadow = trueShadow ? shadowAt(data.z) : shadow.clone(true);
|
data.shadow = trueShadow ? shadowAt(data.z) : shadow.clone(true);
|
||||||
data.slice.shadow = data.shadow;
|
data.slice.shadow = data.shadow;
|
||||||
// data.slice.tops[0].inner = data.shadow;
|
|
||||||
// data.slice.tops[0].inner = POLY.setZ(tshadow.clone(true), data.z);
|
|
||||||
slices.push(data.slice);
|
slices.push(data.slice);
|
||||||
progress(0.25 + 0.25 * (++cnt / tot));
|
progress(0.25 + 0.25 * (++cnt / tot));
|
||||||
}, progress: (index, total) => {
|
}, progress: (index, total) => {
|
||||||
|
|
@ -291,9 +293,9 @@ class OpRough extends CamOp {
|
||||||
} });
|
} });
|
||||||
|
|
||||||
if (trueShadow) {
|
if (trueShadow) {
|
||||||
shadow = tshadow.clone(true);
|
shadow = state.shadow.base.clone(true);
|
||||||
} else {
|
} else {
|
||||||
shadow = POLY.union(shadow.appendAll(shadowTop.tops), 0.01, true);
|
shadow = POLY.union(shadow.appendAll(state.shadow.base), 0.01, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// inset or eliminate thru holes from shadow
|
// inset or eliminate thru holes from shadow
|
||||||
|
|
@ -301,10 +303,6 @@ class OpRough extends CamOp {
|
||||||
thruHoles.forEach(hole => {
|
thruHoles.forEach(hole => {
|
||||||
shadow = shadow.map(p => {
|
shadow = shadow.map(p => {
|
||||||
if (p.isEquivalent(hole)) {
|
if (p.isEquivalent(hole)) {
|
||||||
// eliminate thru holes when roughing voids enabled
|
|
||||||
// if (op.voids) {
|
|
||||||
// return undefined;
|
|
||||||
// }
|
|
||||||
let po = POLY.offset([p], -(toolDiam / 2 + roughLeave + 0.01));
|
let po = POLY.offset([p], -(toolDiam / 2 + roughLeave + 0.01));
|
||||||
return po ? po[0] : undefined;
|
return po ? po[0] : undefined;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -314,6 +312,7 @@ class OpRough extends CamOp {
|
||||||
});
|
});
|
||||||
shadow = POLY.nest(shadow);
|
shadow = POLY.nest(shadow);
|
||||||
if (op.voids) {
|
if (op.voids) {
|
||||||
|
// eliminate voids from shadow when "clear voids" enables
|
||||||
for (let s of shadow) s.inner = undefined;
|
for (let s of shadow) s.inner = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -442,6 +441,7 @@ class OpRough extends CamOp {
|
||||||
setTool(op.tool, op.rate, op.plunge);
|
setTool(op.tool, op.rate, op.plunge);
|
||||||
setSpindle(op.spindle);
|
setSpindle(op.spindle);
|
||||||
|
|
||||||
|
// output the clearing of stock above roughing
|
||||||
for (let slice of (camFaces || [])) {
|
for (let slice of (camFaces || [])) {
|
||||||
const level = [];
|
const level = [];
|
||||||
for (let poly of slice.camLines) {
|
for (let poly of slice.camLines) {
|
||||||
|
|
@ -463,6 +463,7 @@ class OpRough extends CamOp {
|
||||||
newLayer();
|
newLayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// output the roughing passes
|
||||||
setPrintPoint(printPoint);
|
setPrintPoint(printPoint);
|
||||||
sliceOutput(sliceOut, {
|
sliceOutput(sliceOut, {
|
||||||
cutdir,
|
cutdir,
|
||||||
|
|
@ -481,7 +482,7 @@ class OpOutline extends CamOp {
|
||||||
async slice(progress) {
|
async slice(progress) {
|
||||||
let { op, state } = this;
|
let { op, state } = this;
|
||||||
let { settings, widget, slicer, addSlices, tshadow, thruHoles, unsafe, color } = state;
|
let { settings, widget, slicer, addSlices, tshadow, thruHoles, unsafe, color } = state;
|
||||||
let { updateToolDiams, zThru, zBottom, shadowTop, tabs, cutTabs, cutPolys } = state;
|
let { updateToolDiams, zThru, zBottom, tabs, cutTabs, cutPolys } = state;
|
||||||
let { zMax, ztOff } = state;
|
let { zMax, ztOff } = state;
|
||||||
let { process, stock } = settings;
|
let { process, stock } = settings;
|
||||||
|
|
||||||
|
|
@ -540,7 +541,7 @@ class OpOutline extends CamOp {
|
||||||
tot = total;
|
tot = total;
|
||||||
progress((index / total) * 0.5);
|
progress((index / total) * 0.5);
|
||||||
} });
|
} });
|
||||||
shadow = POLY.union(shadow.appendAll(shadowTop.tops), 0.01, true);
|
shadow = POLY.union(shadow.appendAll(state.shadow.base), 0.01, true);
|
||||||
|
|
||||||
// start slices at top of stock when `clear top` enabled
|
// start slices at top of stock when `clear top` enabled
|
||||||
if (op.top) {
|
if (op.top) {
|
||||||
|
|
@ -948,7 +949,7 @@ class OpTrace extends CamOp {
|
||||||
async slice(progress) {
|
async slice(progress) {
|
||||||
let { op, state } = this;
|
let { op, state } = this;
|
||||||
let { tool, rate, down, plunge, offset, offover, thru } = op;
|
let { tool, rate, down, plunge, offset, offover, thru } = op;
|
||||||
let { settings, widget, addSlices, zMax, zTop, zThru, tabs } = state;
|
let { settings, widget, addSlices, zThru, tabs, workarea } = state;
|
||||||
let { updateToolDiams, cutTabs, cutPolys, healPolys, color } = state;
|
let { updateToolDiams, cutTabs, cutPolys, healPolys, color } = state;
|
||||||
let { process, stock } = settings;
|
let { process, stock } = settings;
|
||||||
let { camStockClipTo, camZBottom } = process;
|
let { camStockClipTo, camZBottom } = process;
|
||||||
|
|
@ -956,6 +957,7 @@ class OpTrace extends CamOp {
|
||||||
throw 'trace op not supported with indexed stock';
|
throw 'trace op not supported with indexed stock';
|
||||||
}
|
}
|
||||||
// generate tracing offsets from chosen features
|
// generate tracing offsets from chosen features
|
||||||
|
let zTop = workarea.top_z;
|
||||||
let sliceOut = this.sliceOut = [];
|
let sliceOut = this.sliceOut = [];
|
||||||
let areas = op.areas[widget.id] || [];
|
let areas = op.areas[widget.id] || [];
|
||||||
let camTool = new CAM.Tool(settings, tool);
|
let camTool = new CAM.Tool(settings, tool);
|
||||||
|
|
@ -1002,7 +1004,7 @@ class OpTrace extends CamOp {
|
||||||
slice.camLines = cutPolys([stockRect], slice.camLines, z, true);
|
slice.camLines = cutPolys([stockRect], slice.camLines, z, true);
|
||||||
}
|
}
|
||||||
slice.output()
|
slice.output()
|
||||||
.setLayer("follow", {line: color}, false)
|
.setLayer("trace follow", {line: color}, false)
|
||||||
.addPolys(slice.camLines)
|
.addPolys(slice.camLines)
|
||||||
}
|
}
|
||||||
function clearZ(polys, z, down) {
|
function clearZ(polys, z, down) {
|
||||||
|
|
@ -1023,7 +1025,7 @@ class OpTrace extends CamOp {
|
||||||
}
|
}
|
||||||
POLY.setWinding(slice.camLines, cutdir, false);
|
POLY.setWinding(slice.camLines, cutdir, false);
|
||||||
slice.output()
|
slice.output()
|
||||||
.setLayer("clear", {line: color}, false)
|
.setLayer("trace clear", {line: color}, false)
|
||||||
.addPolys(slice.camLines)
|
.addPolys(slice.camLines)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1185,8 +1187,8 @@ class OpPocket extends CamOp {
|
||||||
const debug = false;
|
const debug = false;
|
||||||
let { op, state } = this;
|
let { op, state } = this;
|
||||||
let { tool, rate, down, plunge, expand, contour, smooth, tolerance } = op;
|
let { tool, rate, down, plunge, expand, contour, smooth, tolerance } = op;
|
||||||
let { settings, widget, addSlices, zTop, zBottom, zThru, tabs, color } = state;
|
let { settings, widget, addSlices, zBottom, zThru, tabs, color } = state;
|
||||||
let { updateToolDiams, cutTabs, cutPolys, healPolys, shadowAt } = state;
|
let { updateToolDiams, cutTabs, cutPolys, healPolys, shadowAt, workarea } = state;
|
||||||
let { process, stock } = settings;
|
let { process, stock } = settings;
|
||||||
// generate tracing offsets from chosen features
|
// generate tracing offsets from chosen features
|
||||||
let sliceOut;
|
let sliceOut;
|
||||||
|
|
@ -1196,6 +1198,7 @@ class OpPocket extends CamOp {
|
||||||
let toolOver = toolDiam * op.step;
|
let toolOver = toolDiam * op.step;
|
||||||
let cutdir = process.camConventional;
|
let cutdir = process.camConventional;
|
||||||
let engrave = contour && op.engrave;
|
let engrave = contour && op.engrave;
|
||||||
|
let zTop = workarea.top_z;
|
||||||
if (contour) {
|
if (contour) {
|
||||||
down = 0;
|
down = 0;
|
||||||
this.topo = await CAM.Topo({
|
this.topo = await CAM.Topo({
|
||||||
|
|
@ -1230,7 +1233,7 @@ class OpPocket extends CamOp {
|
||||||
return slice;
|
return slice;
|
||||||
}
|
}
|
||||||
function clearZ(polys, z, down) {
|
function clearZ(polys, z, down) {
|
||||||
console.log({ clearZ: polys });
|
// console.log({ clearZ: polys });
|
||||||
if (down) {
|
if (down) {
|
||||||
// adjust step down to a value <= down that
|
// adjust step down to a value <= down that
|
||||||
// ends on the lowest z specified
|
// ends on the lowest z specified
|
||||||
|
|
@ -1720,6 +1723,18 @@ class OpXRay extends CamOp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the Part "shadow" and attaches relevant data to the "state" object
|
||||||
|
*
|
||||||
|
* The part shadow consists of top-cown layers at which the polygon shadow changes
|
||||||
|
* shape. For curved or sloped surfaces, this is approximated and paths that clip
|
||||||
|
* to it should use the next lower layer from current Z to ensure no part collisions.
|
||||||
|
*
|
||||||
|
* The shadow at each layer is computed by top-down unioning the part outline with
|
||||||
|
* the shadow from the layer above.
|
||||||
|
*
|
||||||
|
* This operation is injected at the start of the operation chain before processing.
|
||||||
|
*/
|
||||||
class OpShadow extends CamOp {
|
class OpShadow extends CamOp {
|
||||||
constructor(state, op) {
|
constructor(state, op) {
|
||||||
super(state, op);
|
super(state, op);
|
||||||
|
|
@ -1738,7 +1753,9 @@ class OpShadow extends CamOp {
|
||||||
|
|
||||||
let tslices = [];
|
let tslices = [];
|
||||||
let tshadow = [];
|
let tshadow = [];
|
||||||
let tzindex = slicer.interval(minStepDown, { fit: true, off: 0.01, down: true, flats: true });
|
let tzindex = slicer.interval(minStepDown, {
|
||||||
|
fit: true, off: 0.01, down: true, flats: true
|
||||||
|
});
|
||||||
let skipTerrain = unsafe;
|
let skipTerrain = unsafe;
|
||||||
|
|
||||||
if (skipTerrain) {
|
if (skipTerrain) {
|
||||||
|
|
@ -1749,10 +1766,14 @@ class OpShadow extends CamOp {
|
||||||
let lsz; // only shadow up to bottom of last shadow for progressive union
|
let lsz; // only shadow up to bottom of last shadow for progressive union
|
||||||
let cnt = 0;
|
let cnt = 0;
|
||||||
let tot = 0;
|
let tot = 0;
|
||||||
|
|
||||||
|
// terrain is the "shadow stack" where index 0 = top of part
|
||||||
|
// thus array.length -1 = bottom of part
|
||||||
let terrain = await slicer.slice(tzindex, { each: data => {
|
let terrain = await slicer.slice(tzindex, { each: data => {
|
||||||
let shadow = trueShadow ? shadowAt(data.z, lsz) : [];
|
let shadow = trueShadow ? shadowAt(data.z, lsz) : [];
|
||||||
tshadow = POLY.union(tshadow.slice().appendAll(data.tops).appendAll(shadow), 0.01, true);
|
tshadow = POLY.union(tshadow.slice().appendAll(data.tops).appendAll(shadow), 0.01, true);
|
||||||
tslices.push(data.slice);
|
tslices.push(data.slice);
|
||||||
|
// capture current shadow for this slice
|
||||||
data.slice.shadow = tshadow;
|
data.slice.shadow = tshadow;
|
||||||
if (false) {
|
if (false) {
|
||||||
const slice = data.slice;
|
const slice = data.slice;
|
||||||
|
|
@ -1787,14 +1808,23 @@ class OpShadow extends CamOp {
|
||||||
throw `invalid widget shadow`;
|
throw `invalid widget shadow`;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.shadowTop = terrain[terrain.length - 1];
|
// TODO: deprecate use of separate shadow vars in state
|
||||||
state.center = tshadow[0].bounds.center();
|
state.center = tshadow[0].bounds.center();
|
||||||
state.tshadow = tshadow; // true shadow (bottom of part)
|
state.tshadow = tshadow; // true shadow (base of part)
|
||||||
state.terrain = terrain; // stack of shadow slices with tops
|
state.terrain = terrain; // stack of shadow slices stored in tops
|
||||||
state.tslices = tslices;
|
state.tslices = tslices; // raw slicer 'data' layer outputs
|
||||||
state.skipTerrain = skipTerrain;
|
state.skipTerrain = skipTerrain;
|
||||||
|
|
||||||
// identify through holes
|
// TODO: refactor ops to use a unified shadow object
|
||||||
|
state.shadow = {
|
||||||
|
base: tshadow, // computed shadow union at base of part
|
||||||
|
stack: terrain, // stack of shadow slices
|
||||||
|
slices: tslices, // raw slicer 'data' objects
|
||||||
|
skip: skipTerrain
|
||||||
|
};
|
||||||
|
|
||||||
|
// identify through holes which are inner/child polygons
|
||||||
|
// on the bottom-most layer of the shadow stack (tshadow, index == 0)
|
||||||
state.thruHoles = tshadow.map(p => p.inner || []).flat();
|
state.thruHoles = tshadow.map(p => p.inner || []).flat();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
gapp.register("kiri-mode.cam.slice", (root, exports) => {
|
gapp.register("kiri-mode.cam.slice", (root, exports) => {
|
||||||
|
|
||||||
const { base, kiri } = root;
|
const { base, kiri } = root;
|
||||||
|
const { util } = base;
|
||||||
const { driver, newSlice, setSliceTracker } = kiri;
|
const { driver, newSlice, setSliceTracker } = kiri;
|
||||||
const { polygons, newPoint, newPolygon } = base;
|
const { polygons, newPoint, newPolygon } = base;
|
||||||
const { CAM } = driver;
|
const { CAM } = driver;
|
||||||
|
|
@ -35,6 +36,7 @@ CAM.slice = async function(settings, widget, onupdate, ondone) {
|
||||||
sliceAll = widget.slices = [],
|
sliceAll = widget.slices = [],
|
||||||
bounds = widget.getBoundingBox(),
|
bounds = widget.getBoundingBox(),
|
||||||
track = widget.track,
|
track = widget.track,
|
||||||
|
{ camZTop, camZBottom, camZThru } = proc,
|
||||||
// widget top z as defined by setTopz()
|
// widget top z as defined by setTopz()
|
||||||
wztop = track.top,
|
wztop = track.top,
|
||||||
// distance between top of part and top of stock
|
// distance between top of part and top of stock
|
||||||
|
|
@ -43,11 +45,11 @@ CAM.slice = async function(settings, widget, onupdate, ondone) {
|
||||||
zbOff = isIndexed ? 0 : (wztop - track.box.d),
|
zbOff = isIndexed ? 0 : (wztop - track.box.d),
|
||||||
// defined z bottom offset by distance to stock bottom
|
// defined z bottom offset by distance to stock bottom
|
||||||
// keeps the z bottom relative to the part when z align changes
|
// keeps the z bottom relative to the part when z align changes
|
||||||
zBottom = isIndexed ? proc.camZBottom : proc.camZBottom - zbOff,
|
zBottom = isIndexed ? camZBottom : camZBottom - zbOff,
|
||||||
// greater of widget bottom and z bottom
|
// greater of widget bottom and z bottom
|
||||||
zMin = isIndexed ? bounds.min.z : Math.max(bounds.min.z, zBottom),
|
zMin = isIndexed ? bounds.min.z : Math.max(bounds.min.z, zBottom),
|
||||||
zMax = bounds.max.z,
|
zMax = bounds.max.z,
|
||||||
zThru = proc.camZBottom ? 0 : (proc.camZThru || 0),
|
zThru = camZBottom ? 0 : (camZThru || 0),
|
||||||
zTop = zMax + ztOff,
|
zTop = zMax + ztOff,
|
||||||
minToolDiam = Infinity,
|
minToolDiam = Infinity,
|
||||||
maxToolDiam = -Infinity,
|
maxToolDiam = -Infinity,
|
||||||
|
|
@ -57,7 +59,30 @@ CAM.slice = async function(settings, widget, onupdate, ondone) {
|
||||||
unsafe = proc.camExpertFast,
|
unsafe = proc.camExpertFast,
|
||||||
units = settings.controller.units === 'in' ? 25.4 : 1,
|
units = settings.controller.units === 'in' ? 25.4 : 1,
|
||||||
axisRotation,
|
axisRotation,
|
||||||
axisIndex;
|
axisIndex,
|
||||||
|
// new work area tracking
|
||||||
|
part_size = bounds.dim,
|
||||||
|
bottom_gap = zbOff,
|
||||||
|
bottom_part = 0,
|
||||||
|
bottom_stock = -bottom_gap,
|
||||||
|
bottom_thru = zThru,
|
||||||
|
bottom_z = (camZBottom ? bottom_stock + proc.camZBottom : bottom_part) - bottom_thru,
|
||||||
|
top_stock = zTop,
|
||||||
|
top_part = zMax,
|
||||||
|
top_gap = ztOff,
|
||||||
|
top_z = camZTop ? bottom_stock + camZTop : top_stock,
|
||||||
|
workarea = util.round({
|
||||||
|
top_stock,
|
||||||
|
top_part,
|
||||||
|
top_z,
|
||||||
|
bottom_stock,
|
||||||
|
bottom_part,
|
||||||
|
bottom_z
|
||||||
|
}, 3);
|
||||||
|
|
||||||
|
console.table({ workarea });
|
||||||
|
// console.table({ part_size });
|
||||||
|
// console.table({ stock });
|
||||||
|
|
||||||
if (tabs) {
|
if (tabs) {
|
||||||
// make tab polygons
|
// make tab polygons
|
||||||
|
|
@ -65,7 +90,7 @@ CAM.slice = async function(settings, widget, onupdate, ondone) {
|
||||||
let zero = newPoint(0,0,0);
|
let zero = newPoint(0,0,0);
|
||||||
let point = newPoint(tab.pos.x, tab.pos.y, tab.pos.z);
|
let point = newPoint(tab.pos.x, tab.pos.y, tab.pos.z);
|
||||||
let poly = newPolygon().centerRectangle(zero, tab.dim.x, tab.dim.y);
|
let poly = newPolygon().centerRectangle(zero, tab.dim.x, tab.dim.y);
|
||||||
let tslice = newSlice(0);
|
// let tslice = newSlice(0);
|
||||||
let m4 = new THREE.Matrix4().makeRotationFromQuaternion(
|
let m4 = new THREE.Matrix4().makeRotationFromQuaternion(
|
||||||
new THREE.Quaternion(tab.rot._x, tab.rot._y, tab.rot._z, tab.rot._w)
|
new THREE.Quaternion(tab.rot._x, tab.rot._y, tab.rot._z, tab.rot._w)
|
||||||
);
|
);
|
||||||
|
|
@ -202,7 +227,8 @@ CAM.slice = async function(settings, widget, onupdate, ondone) {
|
||||||
zTop,
|
zTop,
|
||||||
unsafe,
|
unsafe,
|
||||||
color,
|
color,
|
||||||
dark
|
dark,
|
||||||
|
workarea
|
||||||
};
|
};
|
||||||
|
|
||||||
let opList = [
|
let opList = [
|
||||||
|
|
@ -279,7 +305,7 @@ CAM.slice = async function(settings, widget, onupdate, ondone) {
|
||||||
|
|
||||||
// add shadow perimeter to terrain to catch outside moves off part
|
// add shadow perimeter to terrain to catch outside moves off part
|
||||||
let tabpoly = tabs ? tabs.map(tab => tab.poly) : [];
|
let tabpoly = tabs ? tabs.map(tab => tab.poly) : [];
|
||||||
let allpoly = POLY.union([...state.shadowTop.tops, ...tabpoly, ...state.shadowTop.slice.shadow], 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));
|
||||||
|
|
|
||||||
|
|
@ -547,6 +547,7 @@ const conf = exports({
|
||||||
camOriginTop: true,
|
camOriginTop: true,
|
||||||
camZAnchor: "middle",
|
camZAnchor: "middle",
|
||||||
camZOffset: 0,
|
camZOffset: 0,
|
||||||
|
camZTop: 0,
|
||||||
camZBottom: 0,
|
camZBottom: 0,
|
||||||
camZClearance: 1,
|
camZClearance: 1,
|
||||||
camZThru: 0,
|
camZThru: 0,
|
||||||
|
|
|
||||||
|
|
@ -1207,6 +1207,7 @@ gapp.register("kiri.init", (root, exports) => {
|
||||||
_____: newGroup(LANG.cc_menu, $('cam-limits'), { modes:CAM, driven, separator }),
|
_____: newGroup(LANG.cc_menu, $('cam-limits'), { modes:CAM, driven, separator }),
|
||||||
camZAnchor: newSelect(LANG.ou_zanc_s, {title: LANG.ou_zanc_l, action:zAnchorSave, show:() => !ui.camStockIndexed.checked}, "zanchor"),
|
camZAnchor: newSelect(LANG.ou_zanc_s, {title: LANG.ou_zanc_l, action:zAnchorSave, show:() => !ui.camStockIndexed.checked}, "zanchor"),
|
||||||
camZOffset: newInput(LANG.ou_ztof_s, {title:LANG.ou_ztof_l, convert:toFloat, units:true}),
|
camZOffset: newInput(LANG.ou_ztof_s, {title:LANG.ou_ztof_l, convert:toFloat, units:true}),
|
||||||
|
camZTop: newInput(LANG.ou_ztop_s, {title:LANG.ou_ztop_l, convert:toFloat, units:true, trigger: true}),
|
||||||
camZBottom: newInput(LANG.ou_zbot_s, {title:LANG.ou_zbot_l, convert:toFloat, units:true, trigger: true}),
|
camZBottom: newInput(LANG.ou_zbot_s, {title:LANG.ou_zbot_l, convert:toFloat, units:true, trigger: true}),
|
||||||
camZThru: newInput(LANG.ou_ztru_s, {title:LANG.ou_ztru_l, convert:toFloat, bound:bound(0.0,100), units:true, show:() => { return ui.camZBottom.value == 0 }}),
|
camZThru: newInput(LANG.ou_ztru_s, {title:LANG.ou_ztru_l, convert:toFloat, bound:bound(0.0,100), units:true, show:() => { return ui.camZBottom.value == 0 }}),
|
||||||
camZClearance: newInput(LANG.ou_zclr_s, {title:LANG.ou_zclr_l, convert:toFloat, bound:bound(0.01,100), units:true}),
|
camZClearance: newInput(LANG.ou_zclr_s, {title:LANG.ou_zclr_l, convert:toFloat, bound:bound(0.01,100), units:true}),
|
||||||
|
|
|
||||||
|
|
@ -735,8 +735,10 @@ self.kiri.lang['en-us'] = {
|
||||||
ou_zanc_l: ["controls the position of the part","when stock Z exceeds part Z"],
|
ou_zanc_l: ["controls the position of the part","when stock Z exceeds part Z"],
|
||||||
ou_ztof_s: "z offset",
|
ou_ztof_s: "z offset",
|
||||||
ou_ztof_l: ["offset z anchor","in workspace units"],
|
ou_ztof_l: ["offset z anchor","in workspace units"],
|
||||||
|
ou_ztop_s: "z top",
|
||||||
|
ou_ztop_l: ["offset from stock bottom","to set start of cutting depth","in workspace units","* Pocket & Trace ONLY *"],
|
||||||
ou_zbot_s: "z bottom",
|
ou_zbot_s: "z bottom",
|
||||||
ou_zbot_l: ["offset from part bottom","to limit cutting depth","in workspace units"],
|
ou_zbot_l: ["offset from stock bottom","to limit cutting depth","in workspace units"],
|
||||||
ou_zclr_s: "z clearance",
|
ou_zclr_s: "z clearance",
|
||||||
ou_zclr_l: ["safe travel offset","from top of part","in workspace units"],
|
ou_zclr_l: ["safe travel offset","from top of part","in workspace units"],
|
||||||
ou_ztru_s: "z thru",
|
ou_ztru_s: "z thru",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue