2020-06-03 22:39:30 -04:00
|
|
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
|
|
|
|
if (!self.kiri.driver) self.kiri.driver = { };
|
|
|
|
|
if (self.kiri.driver.CAM) return;
|
|
|
|
|
|
2020-06-03 22:39:30 -04:00
|
|
|
const KIRI = self.kiri,
|
2017-04-18 17:09:33 -04:00
|
|
|
BASE = self.base,
|
|
|
|
|
UTIL = BASE.util,
|
|
|
|
|
POLY = BASE.polygons,
|
|
|
|
|
CAM = KIRI.driver.CAM = {
|
2020-06-11 22:11:19 -04:00
|
|
|
init,
|
2020-11-05 15:41:52 -05:00
|
|
|
// slice, // src/mode/cam/slice.js
|
2020-05-16 21:46:22 -04:00
|
|
|
sliceRender,
|
2020-11-05 15:25:27 -05:00
|
|
|
// printSetup, // src/mode/cam/prepare.js
|
|
|
|
|
// printExport, // src/mode/cam/export.js
|
2020-11-05 14:47:18 -05:00
|
|
|
printRender
|
2017-04-18 17:09:33 -04:00
|
|
|
},
|
|
|
|
|
CPRO = CAM.process = {
|
2020-06-29 13:48:52 -04:00
|
|
|
LEVEL: 1,
|
|
|
|
|
ROUGH: 2,
|
|
|
|
|
OUTLINE: 3,
|
|
|
|
|
CONTOUR_X: 4,
|
|
|
|
|
CONTOUR_Y: 5,
|
|
|
|
|
TRACE: 6,
|
|
|
|
|
DRILL: 7
|
2017-04-18 17:09:33 -04:00
|
|
|
},
|
|
|
|
|
newLine = BASE.newLine,
|
|
|
|
|
newSlice = KIRI.newSlice,
|
|
|
|
|
newPoint = BASE.newPoint,
|
2020-11-05 15:41:52 -05:00
|
|
|
newPolygon = BASE.newPolygon;
|
2017-04-18 17:09:33 -04:00
|
|
|
|
2020-06-11 22:11:19 -04:00
|
|
|
function init(kiri, api) {
|
|
|
|
|
api.event.on("mode.set", (mode) => {
|
|
|
|
|
let isCAM = mode === 'CAM';
|
|
|
|
|
$('set-tools').style.display = isCAM ? '' : 'none';
|
|
|
|
|
kiri.space.platform.setColor(isCAM ? 0xeeeeee : 0xcccccc);
|
|
|
|
|
});
|
2020-06-12 16:13:02 -04:00
|
|
|
api.event.on("settings.saved", (settings) => {
|
|
|
|
|
let proc = settings.process;
|
|
|
|
|
api.ui.camTabs.marker.style.display = proc.camTabsOn ? 'flex' : 'none';
|
2020-06-27 23:28:09 -04:00
|
|
|
api.ui.camRough.marker.style.display = proc.camRoughOn ? 'flex' : 'none';
|
2020-07-16 22:03:30 -04:00
|
|
|
api.ui.camDrill.marker.style.display =
|
|
|
|
|
proc.camDrillingOn || proc.camDrillReg !== 'none' ? 'flex' : 'none';
|
2020-11-03 22:56:55 -05:00
|
|
|
api.ui.camOutline.marker.style.display = proc.camOutlineOn ? 'flex' : 'none';
|
2020-06-27 23:28:09 -04:00
|
|
|
api.ui.camContour.marker.style.display =
|
|
|
|
|
proc.camContourXOn || proc.camContourYOn ? 'flex' : 'none';
|
2020-06-12 16:13:02 -04:00
|
|
|
});
|
2020-06-11 22:11:19 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-16 21:46:22 -04:00
|
|
|
// runs in browser main
|
|
|
|
|
function sliceRender(widget) {
|
|
|
|
|
let slices = widget.slices;
|
|
|
|
|
if (!slices) return;
|
|
|
|
|
|
|
|
|
|
slices.forEach(function(slice) {
|
|
|
|
|
let tops = slice.tops,
|
|
|
|
|
layers = slice.layers,
|
|
|
|
|
outline = layers.outline,
|
2020-06-27 23:28:09 -04:00
|
|
|
open = (slice.camMode === CPRO.CONTOUR_X || slice.camMode === CPRO.CONTOUR_Y);
|
2020-05-16 21:46:22 -04:00
|
|
|
|
|
|
|
|
layers.outline.clear(); // slice raw edges
|
|
|
|
|
layers.trace.clear(); // roughing
|
2020-06-29 13:48:52 -04:00
|
|
|
layers.solid.clear(); // outline
|
|
|
|
|
layers.bridge.clear(); // outline x
|
|
|
|
|
layers.flat.clear(); // outline y
|
2020-05-16 21:46:22 -04:00
|
|
|
layers.fill.clear(); // facing
|
|
|
|
|
|
|
|
|
|
tops.forEach(function(top) {
|
|
|
|
|
outline.poly(top.poly, 0x999900, true, open);
|
2020-11-03 21:43:06 -05:00
|
|
|
// if (top.inner) outline.poly(top.inner, 0xdddddd, true);
|
|
|
|
|
if (top.inner) outline.poly(top.inner, 0xff0000, true);
|
2020-05-16 21:46:22 -04:00
|
|
|
});
|
|
|
|
|
|
2020-06-29 13:48:52 -04:00
|
|
|
// various outlining
|
2020-05-16 21:46:22 -04:00
|
|
|
let layer;
|
|
|
|
|
slice.tops.forEach(function(top) {
|
|
|
|
|
switch (slice.camMode) {
|
2020-06-27 23:28:09 -04:00
|
|
|
case CPRO.OUTLINE:
|
2020-05-16 21:46:22 -04:00
|
|
|
layer = layers.solid;
|
|
|
|
|
break;
|
2020-06-27 23:28:09 -04:00
|
|
|
case CPRO.CONTOUR_X:
|
2020-05-16 21:46:22 -04:00
|
|
|
layer = layers.bridge;
|
|
|
|
|
break;
|
2020-06-27 23:28:09 -04:00
|
|
|
case CPRO.CONTOUR_Y:
|
2020-05-16 21:46:22 -04:00
|
|
|
layer = layers.flat;
|
|
|
|
|
break;
|
|
|
|
|
default: // roughing
|
|
|
|
|
layer = layers.trace;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (top.traces) {
|
2020-07-04 13:09:57 -04:00
|
|
|
layer.poly(top.traces, 0x010101, true, null);
|
2020-05-16 21:46:22 -04:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2020-05-17 00:02:51 -04:00
|
|
|
// facing (previously separate. now part of roughing)
|
2020-05-16 21:46:22 -04:00
|
|
|
layer = slice.layers.fill;
|
|
|
|
|
slice.tops.forEach(function(top) {
|
|
|
|
|
if (top.fill_lines) {
|
|
|
|
|
layer.lines(top.fill_lines, fill_color);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
outline.render();
|
|
|
|
|
layers.trace.render();
|
|
|
|
|
layers.solid.render();
|
|
|
|
|
layers.bridge.render();
|
|
|
|
|
layers.flat.render();
|
|
|
|
|
layers.fill.render();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-05 15:25:27 -05:00
|
|
|
function printRender(print) {
|
|
|
|
|
return KIRI.driver.FDM.printRender(print, {aslines: true, color: 0x010101, move_color: 0xcc3333});
|
|
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
|
|
|
|
|
/**
|
2020-11-05 15:25:27 -05:00
|
|
|
* Find top paths to trace when using ball and taper mills
|
|
|
|
|
* in waterline outlining and tracing modes.
|
2017-04-18 17:09:33 -04:00
|
|
|
*/
|
2020-11-05 15:25:27 -05:00
|
|
|
function findTracingPaths(widget, slice, tool, profile, partial) {
|
|
|
|
|
// for now, only emit completed polys and not segments
|
|
|
|
|
// TODO consider limiting to nup path lengths that are >= tool radius
|
|
|
|
|
let only_whole = !partial;
|
|
|
|
|
// check for ball and taper mills paths and add to top[0].inner
|
|
|
|
|
let polys = [];
|
|
|
|
|
let nups = [];
|
|
|
|
|
let cull = [];
|
|
|
|
|
slice.gatherTopPolys([]).forEach(poly => poly.flattenTo(polys));
|
|
|
|
|
polys.forEach(poly => {
|
|
|
|
|
let pz = poly.first().z;
|
|
|
|
|
let mz = -Infinity;
|
|
|
|
|
let np = newPolygon().setOpen();
|
|
|
|
|
let mp = 0;
|
|
|
|
|
// find top poly segments that are not significantly offset
|
|
|
|
|
// from tool profile and add to new polygons which accumulate
|
|
|
|
|
// to the top inner array
|
|
|
|
|
poly.forEachSegment((p1,p2) => {
|
|
|
|
|
let nz = getTopoZPathMax(widget, profile, p1.x, p1.y, p2.x, p2.y);
|
|
|
|
|
if (nz > mz) {
|
|
|
|
|
mz = nz;
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
2020-11-05 15:25:27 -05:00
|
|
|
// this # should be computed from topo resolution
|
|
|
|
|
if (nz - pz < 0.01) {
|
|
|
|
|
mp++
|
|
|
|
|
if (np.length) {
|
|
|
|
|
if (!np.first().isEqual(p2)) {
|
|
|
|
|
np.append(p2);
|
|
|
|
|
} else {
|
|
|
|
|
np.setClosed();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
np.append(p1).append(p2);
|
|
|
|
|
}
|
|
|
|
|
} else if (np.length) {
|
|
|
|
|
if (!only_whole) {
|
|
|
|
|
nups.append(np);
|
|
|
|
|
}
|
|
|
|
|
np = newPolygon().setOpen();
|
2020-11-02 18:53:40 -05:00
|
|
|
}
|
2020-11-05 15:25:27 -05:00
|
|
|
});
|
|
|
|
|
if (np.length) {
|
|
|
|
|
if (np.length === poly.length) {
|
|
|
|
|
np.setClosed();
|
2020-07-08 12:18:15 -04:00
|
|
|
}
|
2020-11-05 15:25:27 -05:00
|
|
|
// if a trace poly has no interruptions for an endmill
|
|
|
|
|
// and it's an inner poly, eliminate it from the parent
|
|
|
|
|
// so it won't be offset.
|
|
|
|
|
let parent = poly.parent;
|
|
|
|
|
if (np.isClosed() && parent) {
|
|
|
|
|
// console.log(slice.z,'cull',poly);
|
|
|
|
|
if (parent.inner) {
|
|
|
|
|
parent.inner = parent.inner.filter(p => p !== poly);
|
|
|
|
|
}
|
|
|
|
|
if (only_whole) {
|
|
|
|
|
nups.append(np);
|
|
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
2020-11-05 15:25:27 -05:00
|
|
|
if (!only_whole) {
|
|
|
|
|
nups.append(np);
|
2018-04-21 18:06:39 -04:00
|
|
|
}
|
2017-04-18 17:09:33 -04:00
|
|
|
}
|
|
|
|
|
});
|
2020-11-05 15:25:27 -05:00
|
|
|
if (nups.length) {
|
|
|
|
|
// console.log(slice.z,'nups',nups.length);
|
|
|
|
|
slice.tops[0].inner = nups;
|
|
|
|
|
}
|
2020-06-09 18:12:59 -04:00
|
|
|
}
|
|
|
|
|
|
2017-04-18 17:09:33 -04:00
|
|
|
})();
|