checkpoint cam pocket contour setup
This commit is contained in:
parent
6d20801efe
commit
56e4206930
6 changed files with 92 additions and 14 deletions
|
|
@ -7,6 +7,8 @@ Full docs @ https://docs.grid.space/projects/kiri-moto
|
||||||
|
|
||||||
* improve CAM animation speeds
|
* improve CAM animation speeds
|
||||||
* add CAM op level part offset parameters for xy and z
|
* add CAM op level part offset parameters for xy and z
|
||||||
|
* add CAM pocket smoothing and contouring which is closer to true 3 axis
|
||||||
|
* fix CAM invalidation of tabs on scale and traces on scale or rotate
|
||||||
* fix belt fan override for base extrusions touching belt
|
* fix belt fan override for base extrusions touching belt
|
||||||
|
|
||||||
# Release 3.5 (2022-10-07)
|
# Release 3.5 (2022-10-07)
|
||||||
|
|
|
||||||
|
|
@ -1629,6 +1629,8 @@ class Polygon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cut poly using array of closed polygons. used primarily in cnc
|
||||||
|
// to cut perimeters using tabs resulting in open poly lines.
|
||||||
cut(polys, inter) {
|
cut(polys, inter) {
|
||||||
let target = this;
|
let target = this;
|
||||||
|
|
||||||
|
|
@ -1670,7 +1672,7 @@ class Polygon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find the intersection of two polygons
|
||||||
intersect(poly, min) {
|
intersect(poly, min) {
|
||||||
if (!this.overlaps(poly)) return null;
|
if (!this.overlaps(poly)) return null;
|
||||||
|
|
||||||
|
|
@ -1793,6 +1795,7 @@ class Polygon {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// turn 2d polygon into closed 3d mesh faces
|
||||||
extrude(z = 1) {
|
extrude(z = 1) {
|
||||||
let poly = this.clone().setClockwise();
|
let poly = this.clone().setClockwise();
|
||||||
let faces = [];
|
let faces = [];
|
||||||
|
|
@ -1810,6 +1813,42 @@ class Polygon {
|
||||||
}
|
}
|
||||||
return faces;
|
return faces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// split long straight lines into segments no longer than max
|
||||||
|
// and return a new polygon
|
||||||
|
segment(max = 1) {
|
||||||
|
const newp = [];
|
||||||
|
const points = this.points;
|
||||||
|
const length = points.length;
|
||||||
|
for (let i=0, p=points, l1=length, l2=l1+1; i<l1; i++) {
|
||||||
|
const p1 = p[i];
|
||||||
|
const p2 = p[(i + 1) % l1];
|
||||||
|
const dx = p2.x - p1.x;
|
||||||
|
const dy = p2.y - p1.y;
|
||||||
|
const dl = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
newp.push(p1);
|
||||||
|
if (dl < max) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const div = dl / dist;
|
||||||
|
const fit = div | 0;
|
||||||
|
const add = fit - 1;
|
||||||
|
const ix = dx / fit;
|
||||||
|
const iy = dy / fit;
|
||||||
|
let ox = p1.x + ix;
|
||||||
|
let oy = p1.y + iy;
|
||||||
|
for (let i=0; i<add; i++) {
|
||||||
|
newp.push(new Point(undefined, ox, oy));
|
||||||
|
ox += ix;
|
||||||
|
oy += iy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newp.length > length) {
|
||||||
|
return newPolygon().addPoints(newp.map(p => p.clone()));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// use Slope.angleDiff() then re-test path mitering / rendering
|
// use Slope.angleDiff() then re-test path mitering / rendering
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,7 @@ CAM.init = function(kiri, api) {
|
||||||
"selection.scale",
|
"selection.scale",
|
||||||
"selection.rotate"
|
"selection.rotate"
|
||||||
], () => {
|
], () => {
|
||||||
|
if (!isCamMode) return;
|
||||||
for (let op of current.process.ops) {
|
for (let op of current.process.ops) {
|
||||||
if (op.type === 'trace') {
|
if (op.type === 'trace') {
|
||||||
op.areas = {};
|
op.areas = {};
|
||||||
|
|
@ -1140,6 +1141,8 @@ CAM.init = function(kiri, api) {
|
||||||
rate: 'camPocketSpeed',
|
rate: 'camPocketSpeed',
|
||||||
plunge: 'camPocketPlunge',
|
plunge: 'camPocketPlunge',
|
||||||
expand: 'camPocketExpand',
|
expand: 'camPocketExpand',
|
||||||
|
smooth: 'camPocketSmooth',
|
||||||
|
contour: 'camPocketContour',
|
||||||
outline: 'cmaPocketOutline'
|
outline: 'cmaPocketOutline'
|
||||||
}).inputs = {
|
}).inputs = {
|
||||||
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
|
|
@ -1150,8 +1153,11 @@ CAM.init = function(kiri, api) {
|
||||||
rate: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:UC.toInt, units:true}),
|
rate: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:UC.toInt, units:true}),
|
||||||
plunge: UC.newInput(LANG.cc_plng_s, {title:LANG.cc_plng_l, convert:UC.toInt, units:true}),
|
plunge: UC.newInput(LANG.cc_plng_s, {title:LANG.cc_plng_l, convert:UC.toInt, units:true}),
|
||||||
sep: UC.newBlank({class:"pop-sep"}),
|
sep: UC.newBlank({class:"pop-sep"}),
|
||||||
expand: UC.newInput(LANG.cp_xpnd_s, {title:LANG.cp_xpnd_l, convert:UC.toFloat, units:true}),
|
expand: UC.newInput(LANG.cp_xpnd_s, {title:LANG.cp_xpnd_l, convert:UC.toFloat, units:true, show:() => !poppedRec.contour}),
|
||||||
outline: UC.newBoolean(LANG.cp_outl_s, undefined, {title:LANG.cp_outl_l}),
|
smooth: UC.newInput(LANG.cp_smoo_s, {title:LANG.cp_smoo_l, convert:UC.toFloat, units:true}),
|
||||||
|
sep: UC.newBlank({class:"pop-sep"}),
|
||||||
|
contour: UC.newBoolean(LANG.cp_cont_s, undefined, {title:LANG.cp_cont_s}),
|
||||||
|
outline: UC.newBoolean(LANG.cp_outl_s, undefined, {title:LANG.cp_outl_l, show:() => !poppedRec.contour}),
|
||||||
sep: UC.newBlank({class:"pop-sep"}),
|
sep: UC.newBlank({class:"pop-sep"}),
|
||||||
menu: UC.newRow([
|
menu: UC.newRow([
|
||||||
UC.newButton(undefined, func.surfaceAdd, {icon:'<i class="fas fa-plus"></i>'}),
|
UC.newButton(undefined, func.surfaceAdd, {icon:'<i class="fas fa-plus"></i>'}),
|
||||||
|
|
|
||||||
|
|
@ -957,8 +957,9 @@ class OpPocket extends CamOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
slice(progress) {
|
slice(progress) {
|
||||||
|
const debug = true;
|
||||||
let { op, state } = this;
|
let { op, state } = this;
|
||||||
let { tool, rate, down, plunge, expand } = op;
|
let { tool, rate, down, plunge, expand, contour, smooth } = op;
|
||||||
let { settings, widget, sliceAll, zMax, zTop, zThru, tabs, color } = state;
|
let { settings, widget, sliceAll, zMax, zTop, zThru, tabs, color } = state;
|
||||||
let { updateToolDiams, cutTabs, cutPolys, healPolys, shadowAt } = state;
|
let { updateToolDiams, cutTabs, cutPolys, healPolys, shadowAt } = state;
|
||||||
let { process, stock } = settings;
|
let { process, stock } = settings;
|
||||||
|
|
@ -967,6 +968,9 @@ class OpPocket extends CamOp {
|
||||||
let toolDiam = new CAM.Tool(settings, tool).fluteDiameter();
|
let toolDiam = new CAM.Tool(settings, tool).fluteDiameter();
|
||||||
let toolOver = toolDiam * op.step;
|
let toolOver = toolDiam * op.step;
|
||||||
let cutdir = process.camConventional;
|
let cutdir = process.camConventional;
|
||||||
|
if (contour) {
|
||||||
|
down = 0;
|
||||||
|
}
|
||||||
updateToolDiams(toolDiam);
|
updateToolDiams(toolDiam);
|
||||||
if (tabs) {
|
if (tabs) {
|
||||||
tabs.forEach(tab => {
|
tabs.forEach(tab => {
|
||||||
|
|
@ -987,13 +991,32 @@ class OpPocket extends CamOp {
|
||||||
down = diff / Math.ceil(diff / down);
|
down = diff / Math.ceil(diff / down);
|
||||||
}
|
}
|
||||||
let zs = down ? base.util.lerp(zTop, z, down) : [ z ];
|
let zs = down ? base.util.lerp(zTop, z, down) : [ z ];
|
||||||
if (expand) polys = POLY.offset(polys, expand);
|
if (contour) {
|
||||||
|
expand = toolOver;
|
||||||
|
}
|
||||||
|
if (expand) {
|
||||||
|
polys = POLY.offset(polys, expand);
|
||||||
|
}
|
||||||
let zpro = 0, zinc = 1 / (polys.length * zs.length);
|
let zpro = 0, zinc = 1 / (polys.length * zs.length);
|
||||||
for (let poly of polys) {
|
for (let poly of polys) {
|
||||||
for (let z of zs) {
|
for (let z of zs) {
|
||||||
let shadow = shadowAt(z);
|
let clip = [], shadow;
|
||||||
let clip = [];
|
if (contour) {
|
||||||
|
if (smooth) {
|
||||||
|
clip = POLY.offset(POLY.offset([ poly ], smooth), -smooth);
|
||||||
|
} else {
|
||||||
|
clip = [ poly ];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
shadow = shadowAt(z);
|
||||||
|
if (smooth) {
|
||||||
|
shadow = POLY.offset(POLY.offset(shadow, smooth), -smooth);
|
||||||
|
}
|
||||||
POLY.subtract([ poly ], shadow, clip);
|
POLY.subtract([ poly ], shadow, clip);
|
||||||
|
}
|
||||||
|
if (clip.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let slice = newSliceOut(z);
|
let slice = newSliceOut(z);
|
||||||
slice.camTrace = { tool, rate, plunge };
|
slice.camTrace = { tool, rate, plunge };
|
||||||
POLY.offset(clip, [ -toolDiam / 2, -toolOver ], {
|
POLY.offset(clip, [ -toolDiam / 2, -toolOver ], {
|
||||||
|
|
@ -1008,7 +1031,7 @@ class OpPocket extends CamOp {
|
||||||
slice.output()
|
slice.output()
|
||||||
.setLayer("pocket", {line: color}, false)
|
.setLayer("pocket", {line: color}, false)
|
||||||
.addPolys(slice.camLines)
|
.addPolys(slice.camLines)
|
||||||
if (false) slice.output()
|
if (debug && shadow) slice.output()
|
||||||
.setLayer("pocket shadow", {line: 0xff8811}, false)
|
.setLayer("pocket shadow", {line: 0xff8811}, false)
|
||||||
.addPolys(shadow)
|
.addPolys(shadow)
|
||||||
progress(zpro += zinc, "pocket");
|
progress(zpro += zinc, "pocket");
|
||||||
|
|
@ -1032,15 +1055,17 @@ class OpPocket extends CamOp {
|
||||||
outline = POLY.union(outline, 0.0001, true);
|
outline = POLY.union(outline, 0.0001, true);
|
||||||
outline = POLY.setWinding(outline, cutdir, false);
|
outline = POLY.setWinding(outline, cutdir, false);
|
||||||
outline = healPolys(outline);
|
outline = healPolys(outline);
|
||||||
let pinc = 1;
|
if (smooth) {
|
||||||
|
outline = POLY.offset(POLY.offset(outline, smooth), -smooth);
|
||||||
|
}
|
||||||
if (outline.length) {
|
if (outline.length) {
|
||||||
// option to skip interior features (holes, pillars)
|
// option to skip interior features (holes, pillars)
|
||||||
if (op.outline) {
|
if (!contour && op.outline) {
|
||||||
for (let p of outline) {
|
for (let p of outline) {
|
||||||
p.inner = undefined;
|
p.inner = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (false) newSliceOut(zmin).output()
|
if (debug) newSliceOut(zmin).output()
|
||||||
.setLayer("pocket area", {line: 0x1188ff}, false)
|
.setLayer("pocket area", {line: 0x1188ff}, false)
|
||||||
.addPolys(outline)
|
.addPolys(outline)
|
||||||
clearZ(outline, zmin + 0.0001, down);
|
clearZ(outline, zmin + 0.0001, down);
|
||||||
|
|
@ -1055,7 +1080,7 @@ class OpPocket extends CamOp {
|
||||||
setTool(op.tool, op.rate);
|
setTool(op.tool, op.rate);
|
||||||
setSpindle(op.spindle);
|
setSpindle(op.spindle);
|
||||||
let i=0, l=sliceOut.length;
|
let i=0, l=sliceOut.length;
|
||||||
for (let slice of sliceOut) {
|
for (let slice of sliceOut.filter(s => s.camLines)) {
|
||||||
ops.emitTrace(slice);
|
ops.emitTrace(slice);
|
||||||
progress(++i / l, "pocket");
|
progress(++i / l, "pocket");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -509,6 +509,8 @@ const conf = exports({
|
||||||
camPocketSpeed: 250,
|
camPocketSpeed: 250,
|
||||||
camPocketPlunge: 200,
|
camPocketPlunge: 200,
|
||||||
camPocketExpand: 0,
|
camPocketExpand: 0,
|
||||||
|
camPocketSmooth: 0,
|
||||||
|
camPocketContour: false,
|
||||||
cmaPocketOutline: false,
|
cmaPocketOutline: false,
|
||||||
camDrillTool: 1000,
|
camDrillTool: 1000,
|
||||||
camDrillSpindle: 1000,
|
camDrillSpindle: 1000,
|
||||||
|
|
|
||||||
|
|
@ -515,6 +515,10 @@ self.kiri.lang['en-us'] = {
|
||||||
// CNC POCKET
|
// CNC POCKET
|
||||||
cp_xpnd_s: "expand",
|
cp_xpnd_s: "expand",
|
||||||
cp_xpnd_l: ["grow selected area to","encompass corners"],
|
cp_xpnd_l: ["grow selected area to","encompass corners"],
|
||||||
|
cp_smoo_s: "smooth",
|
||||||
|
cp_smoo_l: ["clean up jagged edges caused by highly angled walls. can speedup pocketing for detailed geometries. recommend a value around 1"],
|
||||||
|
cp_cont_s: "contour",
|
||||||
|
cp_cont_l: ["ignore interior voids and features"],
|
||||||
cp_outl_s: "outline only",
|
cp_outl_s: "outline only",
|
||||||
cp_outl_l: ["ignore interior voids and features"],
|
cp_outl_l: ["ignore interior voids and features"],
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue