checkpoint tracing

This commit is contained in:
Stewart Allen 2020-12-01 18:19:28 -05:00
commit 0ff23ef8cd
11 changed files with 188 additions and 82 deletions

View file

@ -5,8 +5,8 @@
"pre":[ "pre":[
"G21 ; set units to MM (required)", "G21 ; set units to MM (required)",
"G90 ; absolute position mode (required)", "G90 ; absolute position mode (required)",
"G0 F6000 ; default rapid move speed", "G0 F6000 ; default rapid move speed",
"G1 F1500 ; default cutting speed" "G1 F1500 ; default cutting speed"
], ],
"post":[ "post":[
"M30 ; program end" "M30 ; program end"
@ -14,11 +14,15 @@
"tool-change":[ "tool-change":[
"M6 T{tool} ; change tool to '{tool_name}'" "M6 T{tool} ; change tool to '{tool_name}'"
], ],
"dwell":[ "dwell":[
"G4 P{time} ; dwell for {time}ms" "G4 P{time} ; dwell for {time}ms"
], ],
"settings": { "settings": {
"bed_width": 760, "ximage_url": "https://static.grid.space/kiri/siencilabs.png",
"bed_depth": 760 "image_url": "https://static.grid.space/kiri/longmill.png",
} "image_scale": 200,
"image_anchor": 8,
"bed_width": 760,
"bed_depth": 760
}
} }

View file

@ -303,11 +303,11 @@
type: 'poly', type: 'poly',
id: this.id, id: this.id,
array: encodePointArray(this.points, state), array: encodePointArray(this.points, state),
open: this.isOpen(),
inner: encode(this.inner, state), inner: encode(this.inner, state),
parent: encode(this.parent, state), parent: encode(this.parent, state),
depth: this.depth, depth: this.depth,
color: this.color color: this.color,
open: this.open
}; };
}; };

View file

@ -437,7 +437,9 @@
camContourXOn: true, camContourXOn: true,
camContourYOn: true, camContourYOn: true,
camTraceTool: 1000, camTraceTool: 1000,
camTraceType: "follow",
camTraceSpeed: 250, camTraceSpeed: 250,
camTracePlunge: 200,
camDrillTool: 1000, camDrillTool: 1000,
camDrillSpindle: 1000, camDrillSpindle: 1000,
camDrillDownSpeed: 250, camDrillDownSpeed: 250,

View file

@ -1610,10 +1610,12 @@
camContourSep: UC.newBlank({class:"pop-sep"}), camContourSep: UC.newBlank({class:"pop-sep"}),
camContourYOn: UC.newBoolean(LANG.cf_liny_s, onBooleanClick, {title:LANG.cf_liny_l, modes:CAM}), camContourYOn: UC.newBoolean(LANG.cf_liny_s, onBooleanClick, {title:LANG.cf_liny_l, modes:CAM}),
camContourXOn: UC.newBoolean(LANG.cf_linx_s, onBooleanClick, {title:LANG.cf_linx_l, modes:CAM}), camContourXOn: UC.newBoolean(LANG.cf_linx_s, onBooleanClick, {title:LANG.cf_linx_l, modes:CAM}),
camTracing: UC.newGroup(LANG.cu_menu, null, {modes:CAM, marker:true}), camTracing: UC.newGroup(LANG.cu_menu, null, {modes:CAM, marker:true}),
camTraceTool: UC.newSelect(LANG.cc_tool, {modes:CAM}), camTraceTool: UC.newSelect(LANG.cc_tool, {modes:CAM}),
camTraceSpeed: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:UC.toInt, modes:CAM}), camTraceType: UC.newSelect(LANG.cu_type_s, {title:LANG.cu_type_l, modes:CAM}, "trace"),
camTraceSep: UC.newBlank({class:"pop-sep"}), camTraceSpeed: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:UC.toInt, modes:CAM}),
camTracePlunge: UC.newInput(LANG.cc_plng_s, {title:LANG.cc_plng_l, convert:UC.toFloat, modes:CAM, units:true}),
camTraceSep: UC.newBlank({class:"pop-sep"}),
camTraceSelect: UC.newRow([ camTraceSelect: UC.newRow([
(UI.traceAdd = UC.newButton(undefined, onButtonClick, {icon:'<i class="fas fa-plus"></i>'})), (UI.traceAdd = UC.newButton(undefined, onButtonClick, {icon:'<i class="fas fa-plus"></i>'})),
(UI.traceDun = UC.newButton(undefined, onButtonClick, {icon:'<i class="fas fa-check"></i>'})), (UI.traceDun = UC.newButton(undefined, onButtonClick, {icon:'<i class="fas fa-check"></i>'})),

View file

@ -177,6 +177,11 @@
{ name: "300" }, { name: "300" },
{ name: "400" }, { name: "400" },
{ name: "500" } { name: "500" }
],
trace: [
{ name: "follow" },
{ name: "out" },
{ name: "in" }
] ]
}; };

View file

@ -15,6 +15,7 @@
isCamMode, isCamMode,
isParsed, isParsed,
camStock, camStock,
current,
API, FDM, SPACE, STACKS, MODES, VIEWS, UI, UC; API, FDM, SPACE, STACKS, MODES, VIEWS, UI, UC;
let zaxis = {x: 0, y: 0, z: 1}, let zaxis = {x: 0, y: 0, z: 1},
@ -41,6 +42,8 @@
func.tabClear(); func.tabClear();
func.traceDone(); func.traceDone();
} }
// do not persist traces across page reloads
func.traceClear();
}); });
api.event.on("view.set", (mode) => { api.event.on("view.set", (mode) => {
@ -52,6 +55,7 @@
}); });
api.event.on("settings.saved", (settings) => { api.event.on("settings.saved", (settings) => {
current = settings;
const proc = settings.process; const proc = settings.process;
let hasTabs = false; let hasTabs = false;
let hasTraces = false; let hasTraces = false;
@ -138,7 +142,7 @@
let showTab, lastTab, tab, iw, ic; let showTab, lastTab, tab, iw, ic;
api.event.on("cam.tabs.add", func.tabAdd = () => { api.event.on("cam.tabs.add", func.tabAdd = () => {
func.traceDone(); func.traceDone();
alert = api.show.alert("&lt;esc&gt; key cancels editing tabs"); alert = api.show.alert("[esc] key cancels tab editing");
api.feature.hover = true; api.feature.hover = true;
func.hover = func.tabHover; func.hover = func.tabHover;
func.hoverUp = func.tabHoverUp; func.hoverUp = func.tabHoverUp;
@ -228,9 +232,11 @@
return; return;
} }
func.tabDone(); func.tabDone();
alert = api.show.alert("&lt;esc&gt; key cancels editing traces"); alert = api.show.alert("analyzing parts...");
traceOn = true; traceOn = true;
KIRI.client.traces(() => { KIRI.client.traces(() => {
api.hide.alert(alert);
alert = api.show.alert("[esc] key cancels trace editing");
KIRI.api.widgets.opacity(0.5); KIRI.api.widgets.opacity(0.5);
KIRI.api.widgets.for(widget => { KIRI.api.widgets.for(widget => {
let stack = new KIRI.Stack(widget.mesh); let stack = new KIRI.Stack(widget.mesh);
@ -239,6 +245,12 @@
let layers = new KIRI.Layers(); let layers = new KIRI.Layers();
layers.setLayer("trace", {line: 0x88aa55}, false).addPoly(poly); layers.setLayer("trace", {line: 0x88aa55}, false).addPoly(poly);
stack.addLayers(layers); stack.addLayers(layers);
stack.meshes.forEach(mesh => {
mesh.trace = {widget, poly};
});
// reset so each mesh array is new for the layer
widget.adds.appendAll(stack.meshes);
stack.meshes = [];
}); });
// for (let [key, val] of Object.entries(widget.sindex)) { // for (let [key, val] of Object.entries(widget.sindex)) {
// console.log('sindex', {key, val}); // console.log('sindex', {key, val});
@ -246,7 +258,6 @@
// layers.setLayer("sindex", {line: 0x55aa88}, false).addPolys(val); // layers.setLayer("sindex", {line: 0x55aa88}, false).addPolys(val);
// stack.addLayers(layers); // stack.addLayers(layers);
// } // }
widget.adds.appendAll(stack.meshes);
}); });
}); });
api.feature.hover = true; api.feature.hover = true;
@ -264,8 +275,10 @@
api.feature.hover = false; api.feature.hover = false;
api.feature.hoverAdds = false; api.feature.hoverAdds = false;
KIRI.api.widgets.for(widget => { KIRI.api.widgets.for(widget => {
widget.adds.removeAll(widget.trace_stack.meshes); if (widget.trace_stack) {
widget.trace_stack.destroy(); widget.adds.removeAll(widget.trace_stack.meshes);
widget.trace_stack.destroy();
}
}); });
}); });
api.event.on("cam.trace.clear", func.traceClear = () => { api.event.on("cam.trace.clear", func.traceClear = () => {
@ -286,20 +299,49 @@
lastTrace = null; lastTrace = null;
return; return;
} }
// if (data.ints.length === 2) {
// console.log(data.ints);
// }
lastTrace = data.int.object; lastTrace = data.int.object;
let material = lastTrace.material[0]; let material = lastTrace.material[0];
let color = material.color; let color = material.color;
let {r, g, b} = color; let {r, g, b} = color;
material.colorSave = {r, g, b}; material.colorSave = {r, g, b};
color.r = 255; color.r = 1;
color.g = 0; color.g = 0;
color.b = 0; color.b = 0;
}; };
func.traceHoverUp = function(int) { func.traceHoverUp = function(int) {
if (int) console.log({traceHoverUp: int}); if (!int) return;
console.log({traceHoverUp: int});
func.traceToggle(int.object);
};
func.traceToggle = function(obj) {
let material = obj.material[0];
let { color, colorSave } = material;
let { widget, poly } = obj.trace;
let wannot = API.widgets.annotate(widget.id);
let atrace = wannot.trace = wannot.trace || [];
let wtrace = widget.trace = widget.trace || [];
let process = current.process;
obj.selected = !obj.selected;
if (obj.selected) {
color.r = colorSave.r = 0.9;
color.g = colorSave.g = 0;
color.b = colorSave.b = 0.1;
poly.traceInfo = {
tool: process.camTraceTool,
speed: process.camTraceSpeed,
plunge: process.camTracePlunge,
path: KIRI.codec.encode(poly)
};
wtrace.push(poly);
atrace.push(poly.traceInfo);
} else {
color.r = colorSave.r = 0x88/255;
color.g = colorSave.g = 0xaa/255;
color.b = colorSave.b = 0x55/255;
wtrace.remove(poly);
atrace.remove(poly.traceInfo);
}
API.conf.save();
}; };
// COMMON TAB/TRACE EVENT HANDLERS // COMMON TAB/TRACE EVENT HANDLERS
@ -326,6 +368,10 @@
return; return;
} }
const {widget, x, y, z} = rot; const {widget, x, y, z} = rot;
if (traceOn) {
func.traceDone();
}
clearTraces(widget);
if (x || y) { if (x || y) {
clearTabs(widget); clearTabs(widget);
} else { } else {
@ -414,6 +460,17 @@
delete API.widgets.annotate(widget.id).tab; delete API.widgets.annotate(widget.id).tab;
} }
function clearTraces(widget) {
Object.values(widget.traces || {}).forEach(rec => {
console.log('clear',rec);
// widget.adds.remove(rec.box);
// widget.mesh.remove(rec.box);
});
widget.traces = {};
widget.trace_stack = null;
delete API.widgets.annotate(widget.id).trace;
}
function addbox() { return FDM.addbox(...arguments)}; function addbox() { return FDM.addbox(...arguments)};
function delbox() { return FDM.delbox(...arguments)}; function delbox() { return FDM.delbox(...arguments)};

View file

@ -32,7 +32,7 @@
send("traces", { settings }, output => { send("traces", { settings }, output => {
KIRI.codec.decode(output).forEach(rec => { KIRI.codec.decode(output).forEach(rec => {
widgets[rec.id].traces = rec.traces; widgets[rec.id].traces = rec.traces;
widgets[rec.id].sindex = rec.sindex; // widgets[rec.id].sindex = rec.sindex;
}); });
ondone(true); ondone(true);
}); });
@ -46,7 +46,7 @@
send.done(KIRI.codec.encode(widgets.map(widget => {return { send.done(KIRI.codec.encode(widgets.map(widget => {return {
id: widget.id, id: widget.id,
traces: widget.traces, traces: widget.traces,
sindex: widget.sindex // sindex: widget.sindex
}}))); }})));
}; };

View file

@ -432,6 +432,19 @@
} }
} }
break; break;
case PRO.TRACE:
console.log({prep_trace: slice});
let { tool, speed, plunge, path } = slice.camTrace;
setTool(tool, speed, plunge);
let traceTool = new CAM.Tool(settings, tool);
let traceToolDiam = traceTool.fluteDiameter();
slice.camLines.forEach(poly => {
poly.forEachPoint(function(point, pidx) {
camOut(point.clone(), pidx > 0);
}, !poly.open);
});
newLayer();
break;
case PRO.DRILL: case PRO.DRILL:
setTool(process.camDrillTool, process.camDrillDownSpeed, process.camDrillDownSpeed); setTool(process.camDrillTool, process.camDrillDownSpeed, process.camDrillDownSpeed);
depthData.drill.appendAll(slice.camLines); depthData.drill.appendAll(slice.camLines);

View file

@ -45,7 +45,7 @@
procContour = procContourX || procContourY, procContour = procContourX || procContourY,
procDrill = proc.camDrillingOn && proc.camDrillDown && proc.camDrillDownSpeed, procDrill = proc.camDrillingOn && proc.camDrillDown && proc.camDrillDownSpeed,
procDrillReg = proc.camDrillReg, procDrillReg = proc.camDrillReg,
procTrace = proc.camTraceOn, // procTrace = proc.camTraceOn,
roughDown = procRough ? proc.camRoughDown : Infinity, roughDown = procRough ? proc.camRoughDown : Infinity,
outlineDown = procOutline ? proc.camOutlineDown : Infinity, outlineDown = procOutline ? proc.camOutlineDown : Infinity,
sliceDepth = Math.max(0.1, Math.min(roughDown, outlineDown) / 3), sliceDepth = Math.max(0.1, Math.min(roughDown, outlineDown) / 3),
@ -66,16 +66,16 @@
if (tabs) { if (tabs) {
// make tab polygons // make tab polygons
tabs.forEach(tab => { tabs.forEach(tab => {
let zero = BASE.newPoint(0,0,0); let zero = newPoint(0,0,0);
let point = BASE.newPoint(tab.pos.x, tab.pos.y, tab.pos.z); let point = newPoint(tab.pos.x, tab.pos.y, tab.pos.z);
let poly = BASE.newPolygon().centerRectangle(zero, tab.dim.x, tab.dim.y); let poly = newPolygon().centerRectangle(zero, tab.dim.x, tab.dim.y);
let tslice = KIRI.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)
); );
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 => BASE.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;
// tslice.output().setLayer("tabs", 0xff0000).addPoly(poly); // tslice.output().setLayer("tabs", 0xff0000).addPoly(poly);
@ -452,8 +452,8 @@
// offset.xout(`slice ${slice.z}`); // offset.xout(`slice ${slice.z}`);
slice.camLines = offset; slice.camLines = offset;
if (true) slice.output() if (false) slice.output()
.setLayer("slice", {line: 0xaaaa00}, true) .setLayer("slice", {line: 0xaaaa00}, false)
.addPolys(slice.topPolys()) .addPolys(slice.topPolys())
slice.output() slice.output()
.setLayer("outline", {face: 0, line: 0}) .setLayer("outline", {face: 0, line: 0})
@ -484,13 +484,27 @@
} }
// generate tracing offsets from chosen features // generate tracing offsets from chosen features
if (procTrace) { {
// todo let proc = settings.process;
// let proc = settings.process; let traces = (settings.widget[widget.id] || {}).trace || [];
// let traceTool = new CAM.Tool(settings, proc.camTraceTool); traces.forEach(trace => {
// let traceToolDiam = traceTool.fluteDiameter(); console.log({trace});
// widget.maxToolDiam = Math.max(maxToolDiam, traceToolDiam); let { tool, path } = trace;
// slice.camMode = PRO.TRACE; let traceTool = new CAM.Tool(settings, tool);
let traceToolDiam = traceTool.fluteDiameter();
let slice = newSlice();
let poly = KIRI.codec.decode(path);
slice.addTop(poly);
slice.camMode = PRO.TRACE;
slice.camLines = [ poly ];
slice.camTrace = trace;
if (true) slice.output()
.setLayer("trace", {line: 0xaa00aa}, false)
.addPolys(slice.topPolys())
sliceAll.push(slice);
maxToolDiam = Math.max(maxToolDiam, traceToolDiam);
console.log({slice});
});
} }
if (procDrill) { if (procDrill) {
@ -537,55 +551,62 @@
.sort((a,b) => b - a); .sort((a,b) => b - a);
// create shadow // create shadow
let sindex = {}; // let sindex = {};
let shadow = []; // let shadow = [];
let sindices = indices.map((v,i) => v > 0 ? v : v + 0.005 ); // let sindices = indices.map((v,i) => v > 0 ? v : v + 0.005);
slicer.slice(sindices, { each: (data, index, total) => { // slicer.slice(sindices, { each: (data, index, total) => {
shadow = POLY.union(shadow.slice().appendAll(data.tops), 0, true); // shadow = POLY.union(shadow.slice().appendAll(data.tops), 0, true);
POLY.setZ(shadow, data.z); // POLY.setZ(shadow, data.z);
sindex[index] = shadow; // sindex[index] = shadow;
}, flatoff: 0 }); // }, flatoff: 0 });
let traces = []; let traces = [];
// find and trim polys (including open) to shadow // find and trim polys (including open) to shadow
let oneach = (data, index, total) => { let oneach = (data, index, total) => {
BASE.polygons.flatten(data.tops,null,true).forEach(poly => { BASE.polygons.flatten(data.tops,null,true).forEach(poly => {
poly.inner = null;
poly.parent = null;
let z = poly.getZ();
for (let i=0, il=traces.length; i<il; i++) { for (let i=0, il=traces.length; i<il; i++) {
let trace = traces[i];
// only compare polys farther apart in Z
if (Math.abs(z - trace.getZ()) > 0.01) {
continue;
}
// do not add duplicates // do not add duplicates
if (traces[i].isEquivalent(poly)) { if (traces[i].isEquivalent(poly)) {
return; return;
} }
} }
traces.push(poly); traces.push(poly);
return;
// do trimming // do trimming
let trimto = sindex[index]; // let trimto = sindex[index];
if (!trimto) { // if (!trimto) {
traces.push(poly); // traces.push(poly);
return; // return;
} // }
trimto = trimto.clone(true); // trimto = trimto.clone(true);
if (poly.open) { // if (poly.open) {
let cuts = poly.cut(trimto); // let cuts = poly.cut(trimto);
if (cuts.length) { // if (cuts.length) {
traces.appendAll(cuts); // traces.appendAll(cuts);
} else { // } else {
traces.push(poly); // traces.push(poly);
} // }
} else { // } else {
let limit = 1000; // let limit = 1000;
while (trimto.length && limit-- > 0) { // while (trimto.length && limit-- > 0) {
let trim = trimto.shift(); // let trim = trimto.shift();
let mask = poly.mask(trim, true); // let mask = poly.mask(trim, true);
if (mask) { // if (mask) {
trimto.appendAll(mask); // trimto.appendAll(mask);
} else { // } else {
traces.push(poly); // traces.push(poly);
} // }
} // }
if (limit === 1000) { // if (limit === 1000) {
traces.push(poly); // traces.push(poly);
} // }
} // }
}); });
}; };
let opts = { each: oneach, over: false, flatoff: 0, edges: true, openok: true }; let opts = { each: oneach, over: false, flatoff: 0, edges: true, openok: true };
@ -593,7 +614,7 @@
opts.over = true; opts.over = true;
slicer.slice(indices, opts); slicer.slice(indices, opts);
widget.traces = traces; widget.traces = traces;
widget.sindex = sindex; // widget.sindex = sindex;
}; };
// drilling op // drilling op

View file

@ -51,7 +51,7 @@
} }
}); });
api.event.on("fdm.supports.add", func.sadd = () => { api.event.on("fdm.supports.add", func.sadd = () => {
alert = api.show.alert("&lt;esc&gt; key cancels editing supports"); alert = api.show.alert("[esc] key cancels support editing");
api.feature.hover = true; api.feature.hover = true;
}); });
api.event.on("fdm.supports.done", func.sdone = () => { api.event.on("fdm.supports.done", func.sdone = () => {

View file

@ -311,8 +311,10 @@ kiri.lang['en-us'] = {
cf_liny_s: "enable x pass", cf_liny_s: "enable x pass",
cf_liny_l: "linear x-axis finishing", cf_liny_l: "linear x-axis finishing",
// CNC CONTOUR // CNC TRACE
cu_menu: "trace", cu_menu: "trace",
cu_type_s: "type",
cu_type_l: "follow = tool tip follows line\nright or left = tool tip\nfollows line offset by tool radius",
// CNC DRILLING // CNC DRILLING
cd_menu: "drill", cd_menu: "drill",