diff --git a/src/dev/cam/Sienci.LongMill b/src/dev/cam/Sienci.LongMill index e0324842..65a854f7 100644 --- a/src/dev/cam/Sienci.LongMill +++ b/src/dev/cam/Sienci.LongMill @@ -5,8 +5,8 @@ "pre":[ "G21 ; set units to MM (required)", "G90 ; absolute position mode (required)", - "G0 F6000 ; default rapid move speed", - "G1 F1500 ; default cutting speed" + "G0 F6000 ; default rapid move speed", + "G1 F1500 ; default cutting speed" ], "post":[ "M30 ; program end" @@ -14,11 +14,15 @@ "tool-change":[ "M6 T{tool} ; change tool to '{tool_name}'" ], - "dwell":[ - "G4 P{time} ; dwell for {time}ms" - ], - "settings": { - "bed_width": 760, - "bed_depth": 760 - } + "dwell":[ + "G4 P{time} ; dwell for {time}ms" + ], + "settings": { + "ximage_url": "https://static.grid.space/kiri/siencilabs.png", + "image_url": "https://static.grid.space/kiri/longmill.png", + "image_scale": 200, + "image_anchor": 8, + "bed_width": 760, + "bed_depth": 760 + } } diff --git a/src/kiri/codec.js b/src/kiri/codec.js index ec9d6a18..bc473e8c 100644 --- a/src/kiri/codec.js +++ b/src/kiri/codec.js @@ -303,11 +303,11 @@ type: 'poly', id: this.id, array: encodePointArray(this.points, state), - open: this.isOpen(), inner: encode(this.inner, state), parent: encode(this.parent, state), depth: this.depth, - color: this.color + color: this.color, + open: this.open }; }; diff --git a/src/kiri/conf.js b/src/kiri/conf.js index 37f01a22..b2b691ad 100644 --- a/src/kiri/conf.js +++ b/src/kiri/conf.js @@ -437,7 +437,9 @@ camContourXOn: true, camContourYOn: true, camTraceTool: 1000, + camTraceType: "follow", camTraceSpeed: 250, + camTracePlunge: 200, camDrillTool: 1000, camDrillSpindle: 1000, camDrillDownSpeed: 250, diff --git a/src/kiri/init.js b/src/kiri/init.js index 183875d0..26fd1bf5 100644 --- a/src/kiri/init.js +++ b/src/kiri/init.js @@ -1610,10 +1610,12 @@ camContourSep: UC.newBlank({class:"pop-sep"}), 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}), - camTracing: UC.newGroup(LANG.cu_menu, null, {modes:CAM, marker:true}), - 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}), - camTraceSep: UC.newBlank({class:"pop-sep"}), + camTracing: UC.newGroup(LANG.cu_menu, null, {modes:CAM, marker:true}), + camTraceTool: UC.newSelect(LANG.cc_tool, {modes:CAM}), + camTraceType: UC.newSelect(LANG.cu_type_s, {title:LANG.cu_type_l, modes:CAM}, "trace"), + 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([ (UI.traceAdd = UC.newButton(undefined, onButtonClick, {icon:''})), (UI.traceDun = UC.newButton(undefined, onButtonClick, {icon:''})), diff --git a/src/kiri/main.js b/src/kiri/main.js index 29df95e2..64e7b798 100644 --- a/src/kiri/main.js +++ b/src/kiri/main.js @@ -177,6 +177,11 @@ { name: "300" }, { name: "400" }, { name: "500" } + ], + trace: [ + { name: "follow" }, + { name: "out" }, + { name: "in" } ] }; diff --git a/src/mode/cam/client.js b/src/mode/cam/client.js index 20a7ee70..1f7221e0 100644 --- a/src/mode/cam/client.js +++ b/src/mode/cam/client.js @@ -15,6 +15,7 @@ isCamMode, isParsed, camStock, + current, API, FDM, SPACE, STACKS, MODES, VIEWS, UI, UC; let zaxis = {x: 0, y: 0, z: 1}, @@ -41,6 +42,8 @@ func.tabClear(); func.traceDone(); } + // do not persist traces across page reloads + func.traceClear(); }); api.event.on("view.set", (mode) => { @@ -52,6 +55,7 @@ }); api.event.on("settings.saved", (settings) => { + current = settings; const proc = settings.process; let hasTabs = false; let hasTraces = false; @@ -138,7 +142,7 @@ let showTab, lastTab, tab, iw, ic; api.event.on("cam.tabs.add", func.tabAdd = () => { func.traceDone(); - alert = api.show.alert("<esc> key cancels editing tabs"); + alert = api.show.alert("[esc] key cancels tab editing"); api.feature.hover = true; func.hover = func.tabHover; func.hoverUp = func.tabHoverUp; @@ -228,9 +232,11 @@ return; } func.tabDone(); - alert = api.show.alert("<esc> key cancels editing traces"); + alert = api.show.alert("analyzing parts..."); traceOn = true; 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.for(widget => { let stack = new KIRI.Stack(widget.mesh); @@ -239,6 +245,12 @@ let layers = new KIRI.Layers(); layers.setLayer("trace", {line: 0x88aa55}, false).addPoly(poly); 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)) { // console.log('sindex', {key, val}); @@ -246,7 +258,6 @@ // layers.setLayer("sindex", {line: 0x55aa88}, false).addPolys(val); // stack.addLayers(layers); // } - widget.adds.appendAll(stack.meshes); }); }); api.feature.hover = true; @@ -264,8 +275,10 @@ api.feature.hover = false; api.feature.hoverAdds = false; KIRI.api.widgets.for(widget => { - widget.adds.removeAll(widget.trace_stack.meshes); - widget.trace_stack.destroy(); + if (widget.trace_stack) { + widget.adds.removeAll(widget.trace_stack.meshes); + widget.trace_stack.destroy(); + } }); }); api.event.on("cam.trace.clear", func.traceClear = () => { @@ -286,20 +299,49 @@ lastTrace = null; return; } - // if (data.ints.length === 2) { - // console.log(data.ints); - // } lastTrace = data.int.object; let material = lastTrace.material[0]; let color = material.color; let {r, g, b} = color; material.colorSave = {r, g, b}; - color.r = 255; + color.r = 1; color.g = 0; color.b = 0; }; 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 @@ -326,6 +368,10 @@ return; } const {widget, x, y, z} = rot; + if (traceOn) { + func.traceDone(); + } + clearTraces(widget); if (x || y) { clearTabs(widget); } else { @@ -414,6 +460,17 @@ 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 delbox() { return FDM.delbox(...arguments)}; diff --git a/src/mode/cam/driver.js b/src/mode/cam/driver.js index e7809691..fc7a0a69 100644 --- a/src/mode/cam/driver.js +++ b/src/mode/cam/driver.js @@ -32,7 +32,7 @@ send("traces", { settings }, output => { KIRI.codec.decode(output).forEach(rec => { widgets[rec.id].traces = rec.traces; - widgets[rec.id].sindex = rec.sindex; + // widgets[rec.id].sindex = rec.sindex; }); ondone(true); }); @@ -46,7 +46,7 @@ send.done(KIRI.codec.encode(widgets.map(widget => {return { id: widget.id, traces: widget.traces, - sindex: widget.sindex + // sindex: widget.sindex }}))); }; diff --git a/src/mode/cam/prepare.js b/src/mode/cam/prepare.js index b560b255..7458f003 100644 --- a/src/mode/cam/prepare.js +++ b/src/mode/cam/prepare.js @@ -432,6 +432,19 @@ } } 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: setTool(process.camDrillTool, process.camDrillDownSpeed, process.camDrillDownSpeed); depthData.drill.appendAll(slice.camLines); diff --git a/src/mode/cam/slice.js b/src/mode/cam/slice.js index c2fccc12..423780b3 100644 --- a/src/mode/cam/slice.js +++ b/src/mode/cam/slice.js @@ -45,7 +45,7 @@ procContour = procContourX || procContourY, procDrill = proc.camDrillingOn && proc.camDrillDown && proc.camDrillDownSpeed, procDrillReg = proc.camDrillReg, - procTrace = proc.camTraceOn, + // procTrace = proc.camTraceOn, roughDown = procRough ? proc.camRoughDown : Infinity, outlineDown = procOutline ? proc.camOutlineDown : Infinity, sliceDepth = Math.max(0.1, Math.min(roughDown, outlineDown) / 3), @@ -66,16 +66,16 @@ if (tabs) { // make tab polygons tabs.forEach(tab => { - let zero = BASE.newPoint(0,0,0); - let point = BASE.newPoint(tab.pos.x, tab.pos.y, tab.pos.z); - let poly = BASE.newPolygon().centerRectangle(zero, tab.dim.x, tab.dim.y); - let tslice = KIRI.newSlice(0); + let zero = newPoint(0,0,0); + let point = newPoint(tab.pos.x, tab.pos.y, tab.pos.z); + let poly = newPolygon().centerRectangle(zero, tab.dim.x, tab.dim.y); + let tslice = newSlice(0); let m4 = new THREE.Matrix4().makeRotationFromQuaternion( new THREE.Quaternion(tab.rot._x, tab.rot._y, tab.rot._z, tab.rot._w) ); poly.points = poly.points .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); tab.poly = poly; // tslice.output().setLayer("tabs", 0xff0000).addPoly(poly); @@ -452,8 +452,8 @@ // offset.xout(`slice ${slice.z}`); slice.camLines = offset; - if (true) slice.output() - .setLayer("slice", {line: 0xaaaa00}, true) + if (false) slice.output() + .setLayer("slice", {line: 0xaaaa00}, false) .addPolys(slice.topPolys()) slice.output() .setLayer("outline", {face: 0, line: 0}) @@ -484,13 +484,27 @@ } // generate tracing offsets from chosen features - if (procTrace) { - // todo - // let proc = settings.process; - // let traceTool = new CAM.Tool(settings, proc.camTraceTool); - // let traceToolDiam = traceTool.fluteDiameter(); - // widget.maxToolDiam = Math.max(maxToolDiam, traceToolDiam); - // slice.camMode = PRO.TRACE; + { + let proc = settings.process; + let traces = (settings.widget[widget.id] || {}).trace || []; + traces.forEach(trace => { + console.log({trace}); + let { tool, path } = 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) { @@ -537,55 +551,62 @@ .sort((a,b) => b - a); // create shadow - let sindex = {}; - let shadow = []; - let sindices = indices.map((v,i) => v > 0 ? v : v + 0.005 ); - slicer.slice(sindices, { each: (data, index, total) => { - shadow = POLY.union(shadow.slice().appendAll(data.tops), 0, true); - POLY.setZ(shadow, data.z); - sindex[index] = shadow; - }, flatoff: 0 }); + // let sindex = {}; + // let shadow = []; + // let sindices = indices.map((v,i) => v > 0 ? v : v + 0.005); + // slicer.slice(sindices, { each: (data, index, total) => { + // shadow = POLY.union(shadow.slice().appendAll(data.tops), 0, true); + // POLY.setZ(shadow, data.z); + // sindex[index] = shadow; + // }, flatoff: 0 }); let traces = []; // find and trim polys (including open) to shadow let oneach = (data, index, total) => { 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 0.01) { + continue; + } // do not add duplicates if (traces[i].isEquivalent(poly)) { return; } } traces.push(poly); - return; // do trimming - let trimto = sindex[index]; - if (!trimto) { - traces.push(poly); - return; - } - trimto = trimto.clone(true); - if (poly.open) { - let cuts = poly.cut(trimto); - if (cuts.length) { - traces.appendAll(cuts); - } else { - traces.push(poly); - } - } else { - let limit = 1000; - while (trimto.length && limit-- > 0) { - let trim = trimto.shift(); - let mask = poly.mask(trim, true); - if (mask) { - trimto.appendAll(mask); - } else { - traces.push(poly); - } - } - if (limit === 1000) { - traces.push(poly); - } - } + // let trimto = sindex[index]; + // if (!trimto) { + // traces.push(poly); + // return; + // } + // trimto = trimto.clone(true); + // if (poly.open) { + // let cuts = poly.cut(trimto); + // if (cuts.length) { + // traces.appendAll(cuts); + // } else { + // traces.push(poly); + // } + // } else { + // let limit = 1000; + // while (trimto.length && limit-- > 0) { + // let trim = trimto.shift(); + // let mask = poly.mask(trim, true); + // if (mask) { + // trimto.appendAll(mask); + // } else { + // traces.push(poly); + // } + // } + // if (limit === 1000) { + // traces.push(poly); + // } + // } }); }; let opts = { each: oneach, over: false, flatoff: 0, edges: true, openok: true }; @@ -593,7 +614,7 @@ opts.over = true; slicer.slice(indices, opts); widget.traces = traces; - widget.sindex = sindex; + // widget.sindex = sindex; }; // drilling op diff --git a/src/mode/fdm/client.js b/src/mode/fdm/client.js index eec69ccb..20caef2e 100644 --- a/src/mode/fdm/client.js +++ b/src/mode/fdm/client.js @@ -51,7 +51,7 @@ } }); api.event.on("fdm.supports.add", func.sadd = () => { - alert = api.show.alert("<esc> key cancels editing supports"); + alert = api.show.alert("[esc] key cancels support editing"); api.feature.hover = true; }); api.event.on("fdm.supports.done", func.sdone = () => { diff --git a/web/kiri/lang/en.js b/web/kiri/lang/en.js index 132613e8..fe09b8bb 100644 --- a/web/kiri/lang/en.js +++ b/web/kiri/lang/en.js @@ -311,8 +311,10 @@ kiri.lang['en-us'] = { cf_liny_s: "enable x pass", cf_liny_l: "linear x-axis finishing", - // CNC CONTOUR + // CNC 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 cd_menu: "drill",