Merge branch 'rel-4.5' of https://github.com/GridSpace/grid-apps into drill-optimization
This commit is contained in:
commit
ce8cbc2c5c
27 changed files with 1190 additions and 581 deletions
|
|
@ -1,9 +1,9 @@
|
||||||
// back end for device export in dev mode
|
// back end for device export in dev mode
|
||||||
module.exports = function(server) {
|
module.exports = function(server) {
|
||||||
server.inject("kiri", "kiri.js");
|
|
||||||
if (!server.env.debug) {
|
if (!server.env.debug) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
server.inject("kiri", "kiri.js");
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
server.api.postDevice = (req, res, next) => {
|
server.api.postDevice = (req, res, next) => {
|
||||||
server.handler.decodePost(req, res, () => {
|
server.handler.decodePost(req, res, () => {
|
||||||
|
|
@ -16,7 +16,7 @@ module.exports = function(server) {
|
||||||
}
|
}
|
||||||
const { mode } = device;
|
const { mode } = device;
|
||||||
const { deviceName } = device;
|
const { deviceName } = device;
|
||||||
const path = `${server.const.rootdir}/src/kiri-dev/${mode.toLowerCase()}/${deviceName.replace(/\ /g,'.')}`;
|
const path = `${server.const.rootdir}/src/kiri/dev/${mode.toLowerCase()}/${deviceName.replace(/\ /g,'.')}`;
|
||||||
// console.log({ mode, device, process, path });
|
// console.log({ mode, device, process, path });
|
||||||
fs.writeFileSync(path, JSON.stringify(device, undefined, 4));
|
fs.writeFileSync(path, JSON.stringify(device, undefined, 4));
|
||||||
res.end('profile saved');
|
res.end('profile saved');
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ self.kiri.load(api => {
|
||||||
let deviceExport = api.device.export;
|
let deviceExport = api.device.export;
|
||||||
api.device.export = (exp, name, opt = {}) => {
|
api.device.export = (exp, name, opt = {}) => {
|
||||||
const { event, record } = opt;
|
const { event, record } = opt;
|
||||||
if (event && event.shiftKey & api.const.LOCAL) {
|
if (event && event.shiftKey) {
|
||||||
const { code, process, profiles } = record;
|
const { code, process, profiles } = record;
|
||||||
fetch("/api/postDevice", {
|
fetch("/api/postDevice", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|
@ -12,7 +12,7 @@ self.kiri.load(api => {
|
||||||
})
|
})
|
||||||
.then(r => r.text())
|
.then(r => r.text())
|
||||||
.then(t => {
|
.then(t => {
|
||||||
// console.log({server_said: t});
|
console.log({server_said: t});
|
||||||
api.show.alert('profile saved to server');
|
api.show.alert('profile saved to server');
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,18 @@ export class Polygon {
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBounds3D(bounds = new THREE.Box3()) {
|
||||||
|
for (let point of this.points) {
|
||||||
|
bounds.expandByPoint(point);
|
||||||
|
}
|
||||||
|
if (this.inner) {
|
||||||
|
for (let i of this.inner) {
|
||||||
|
i.getBounds3D(bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
toPath2D(offset) {
|
toPath2D(offset) {
|
||||||
return paths.pointsToPath(this.points, offset, this.open);
|
return paths.pointsToPath(this.points, offset, this.open);
|
||||||
}
|
}
|
||||||
|
|
@ -985,7 +997,13 @@ export class Polygon {
|
||||||
}
|
}
|
||||||
|
|
||||||
minZ() {
|
minZ() {
|
||||||
return Math.min(...this.points.map(p => p.z));
|
let minZ = Math.min(...this.points.map(p => p.z));
|
||||||
|
if (this.inner) {
|
||||||
|
for (let i of this.inner) {
|
||||||
|
minZ = Math.min(minZ, i.minZ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return minZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
avgZ() {
|
avgZ() {
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,9 @@ let UC = UI.prefix('kiri').inputAction(settings.conf.update),
|
||||||
redo: noop // do.js
|
redo: noop // do.js
|
||||||
},
|
},
|
||||||
devel = {
|
devel = {
|
||||||
|
get enabled() {
|
||||||
|
return settings.ctrl().devel;
|
||||||
|
},
|
||||||
xray(layers, raw) {
|
xray(layers, raw) {
|
||||||
let proc = api.conf.get().process,
|
let proc = api.conf.get().process,
|
||||||
size = proc.sliceHeight || proc.slaSlice || 1,
|
size = proc.sliceHeight || proc.slaSlice || 1,
|
||||||
|
|
|
||||||
|
|
@ -423,6 +423,20 @@ export const conf = {
|
||||||
camArcEnabled: false,
|
camArcEnabled: false,
|
||||||
camArcResolution: 5,
|
camArcResolution: 5,
|
||||||
camArcTolerance: 0.15,
|
camArcTolerance: 0.15,
|
||||||
|
camAreaSpindle: 1000,
|
||||||
|
camAreaTool: 1000,
|
||||||
|
camAreaMode: "clear",
|
||||||
|
camAreaTrace: "none",
|
||||||
|
camAreaSurface: "linear",
|
||||||
|
camAreaAngle: 0,
|
||||||
|
camAreaOver: 0.4,
|
||||||
|
camAreaDown: 1,
|
||||||
|
camAreaSpeed: 1000,
|
||||||
|
camAreaPlunge: 100,
|
||||||
|
camAreaExpand: 0,
|
||||||
|
camAreaSmooth: 1,
|
||||||
|
camAreaRefine: 0,
|
||||||
|
camAreaOutline: false,
|
||||||
camContourAngle: 85,
|
camContourAngle: 85,
|
||||||
camContourBottom: false,
|
camContourBottom: false,
|
||||||
camContourBridge: 0,
|
camContourBridge: 0,
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,15 @@ const LISTS = {
|
||||||
{ name: "adaptive" },
|
{ name: "adaptive" },
|
||||||
{ name: "legacy 1" },
|
{ name: "legacy 1" },
|
||||||
{ name: "legacy 2" }
|
{ name: "legacy 2" }
|
||||||
|
],
|
||||||
|
opmode: [
|
||||||
|
{ name: "clear" },
|
||||||
|
{ name: "trace" },
|
||||||
|
{ name: "surface" }
|
||||||
|
],
|
||||||
|
surftyp: [
|
||||||
|
{ name: "linear" },
|
||||||
|
{ name: "offset" },
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1579,16 +1579,6 @@ function init_two() {
|
||||||
api.event.emit('load.lib', lib);
|
api.event.emit('load.lib', lib);
|
||||||
});
|
});
|
||||||
|
|
||||||
// load CSS extensions
|
|
||||||
if (SETUP.ss) SETUP.ss.forEach(function(style) {
|
|
||||||
style = style.charAt(0) === '/' ? style : `/kiri/style-${style}`;
|
|
||||||
let ss = DOC.createElement('link');
|
|
||||||
ss.setAttribute("type", "text/css");
|
|
||||||
ss.setAttribute("rel", "stylesheet");
|
|
||||||
ss.setAttribute("href", `${style}.css?${version}`);
|
|
||||||
DOC.body.appendChild(ss);
|
|
||||||
});
|
|
||||||
|
|
||||||
// override stored settings
|
// override stored settings
|
||||||
if (SETUP.v) SETUP.v.forEach(function(kv) {
|
if (SETUP.v) SETUP.v.forEach(function(kv) {
|
||||||
kv = kv.split('=');
|
kv = kv.split('=');
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ function onLeftySelect() {
|
||||||
let projectedNormal = new Vector3(lastface.normal.x, lastface.normal.y, 0).normalize();
|
let projectedNormal = new Vector3(lastface.normal.x, lastface.normal.y, 0).normalize();
|
||||||
|
|
||||||
// Target direction on XY plane (negative Y axis)
|
// Target direction on XY plane (negative Y axis)
|
||||||
let targetDir = new Vector3(0, -1, 0);
|
let targetDir = new Vector3(-1, 0, 0);
|
||||||
|
|
||||||
// Calculate angle between projected normal and target
|
// Calculate angle between projected normal and target
|
||||||
let angle = Math.atan2(
|
let angle = Math.atan2(
|
||||||
|
|
|
||||||
|
|
@ -332,6 +332,10 @@ class Widget {
|
||||||
moto.space.refresh();
|
moto.space.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isSynth() {
|
||||||
|
return this.track.synth ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
isVisible() {
|
isVisible() {
|
||||||
return this.getMaterial().visible;
|
return this.getMaterial().visible;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
166
src/kiri/dev/fdm/Creality.Ender.7
Normal file
166
src/kiri/dev/fdm/Creality.Ender.7
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
{
|
||||||
|
"mode": "FDM",
|
||||||
|
"internal": 0,
|
||||||
|
"bedHeight": 2.5,
|
||||||
|
"bedWidth": 252,
|
||||||
|
"bedDepth": 252,
|
||||||
|
"bedRound": false,
|
||||||
|
"bedBelt": false,
|
||||||
|
"deviceZMax": 0,
|
||||||
|
"gcodeTime": 1,
|
||||||
|
"maxHeight": 302,
|
||||||
|
"originCenter": false,
|
||||||
|
"gcodeFan": [
|
||||||
|
"M106 S{fan_speed}"
|
||||||
|
],
|
||||||
|
"gcodeFeature": [],
|
||||||
|
"gcodeTrack": [],
|
||||||
|
"gcodeLayer": [],
|
||||||
|
"gcodePre": [
|
||||||
|
"M140 S{bed_temp}",
|
||||||
|
"M105",
|
||||||
|
"M190 S{bed_temp}",
|
||||||
|
"M104 S{temp}",
|
||||||
|
"M105",
|
||||||
|
"M109 S{temp}",
|
||||||
|
"M82 ; absolute extrusion mode",
|
||||||
|
"G28 ; Home",
|
||||||
|
"G92 E0 ; Reset Extruder",
|
||||||
|
"G1 Z2.0 F3000 ; Move Z Axis up",
|
||||||
|
"G1 X10.1 Y20 Z0.28 F5000.0 ; Move to start position",
|
||||||
|
"G1 X10.1 Y200.0 Z0.28 F1500.0 E15 ; Draw the first line",
|
||||||
|
"G1 X10.4 Y200.0 Z0.28 F5000.0 ; Move to side a little",
|
||||||
|
"G1 X10.4 Y20 Z0.28 F1500.0 E30 ; Draw the second line",
|
||||||
|
"G92 E0 ; Reset Extruder",
|
||||||
|
"G1 Z2.0 F3000 ; Move Z Axis up"
|
||||||
|
],
|
||||||
|
"gcodePost": [
|
||||||
|
"G91 ; Relative positionning",
|
||||||
|
"G1 E-2 F2700 ; Retract a bit",
|
||||||
|
"G1 E-2 Z0.2 F2400 ; Retract and raise Z",
|
||||||
|
"G1 X5 Y5 F3000 ; Wipe out",
|
||||||
|
"G1 Z10 ; Raise Z more",
|
||||||
|
"G90 ; Absolute positionning",
|
||||||
|
"G28 X Y ; Present print",
|
||||||
|
"M106 S0 ; Turn-off fan",
|
||||||
|
"M104 S0 ; Turn-off hotend",
|
||||||
|
"M140 S0 ; Turn-off bed",
|
||||||
|
"M84 X Y E ; Disable all steppers but Z"
|
||||||
|
],
|
||||||
|
"gcodeProc": "",
|
||||||
|
"gcodeChange": [],
|
||||||
|
"gcodeFExt": "gcode",
|
||||||
|
"extruders": [
|
||||||
|
{
|
||||||
|
"extFilament": 1.75,
|
||||||
|
"extNozzle": 0.4,
|
||||||
|
"extOffsetX": 0,
|
||||||
|
"extOffsetY": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"extFilament": 1.75,
|
||||||
|
"extNozzle": 0.4,
|
||||||
|
"extOffsetX": 0,
|
||||||
|
"extOffsetY": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"new": false,
|
||||||
|
"deviceName": "Creality.Ender.7",
|
||||||
|
"imageURL": "",
|
||||||
|
"fwRetract": false,
|
||||||
|
"filamentSource": "direct",
|
||||||
|
"profiles": [
|
||||||
|
{
|
||||||
|
"antiBacklash": 0,
|
||||||
|
"arcTolerance": 0,
|
||||||
|
"firstLayerBedTemp": 60,
|
||||||
|
"firstLayerBeltBump": 0,
|
||||||
|
"firstLayerBeltLead": 3,
|
||||||
|
"firstLayerBeltFact": 1,
|
||||||
|
"firstLayerBrim": 0,
|
||||||
|
"firstLayerBrimGap": 0,
|
||||||
|
"firstLayerBrimIn": 0,
|
||||||
|
"firstLayerBrimTrig": 0,
|
||||||
|
"firstLayerFanSpeed": 0,
|
||||||
|
"firstLayerFillRate": 35,
|
||||||
|
"firstLayerFlatten": 0,
|
||||||
|
"firstLayerNozzleTemp": 210,
|
||||||
|
"firstLayerRate": 30,
|
||||||
|
"firstLayerYOffset": 0,
|
||||||
|
"firstSliceHeight": 0.25,
|
||||||
|
"outputAlternating": false,
|
||||||
|
"outputAvoidGaps": true,
|
||||||
|
"outputBedTemp": 65,
|
||||||
|
"outputBeltFirst": false,
|
||||||
|
"outputBrimCount": 2,
|
||||||
|
"outputBrimOffset": 2,
|
||||||
|
"outputCoastDist": 0,
|
||||||
|
"outputDraftShield": false,
|
||||||
|
"outputFanLayer": 1,
|
||||||
|
"outputFanSpeed": 255,
|
||||||
|
"outputFeedrate": 50,
|
||||||
|
"outputFillMult": 1.25,
|
||||||
|
"outputFinishrate": 50,
|
||||||
|
"outputInvertX": false,
|
||||||
|
"outputInvertY": false,
|
||||||
|
"outputLayerRetract": false,
|
||||||
|
"outputLoops": 0,
|
||||||
|
"outputMaxFlowrate": 15,
|
||||||
|
"outputMinLayerTime": 10,
|
||||||
|
"outputMinSpeed": 5,
|
||||||
|
"outputPurgeTower": 0,
|
||||||
|
"outputRaft": false,
|
||||||
|
"outputRaftSpacing": 0.2,
|
||||||
|
"outputRetractDist": 10,
|
||||||
|
"outputRetractDwell": 20,
|
||||||
|
"outputRetractSpeed": 40,
|
||||||
|
"outputRetractWipe": 0,
|
||||||
|
"outputScarfLength": 0,
|
||||||
|
"outputSeekrate": 250,
|
||||||
|
"outputShellMult": 1.25,
|
||||||
|
"outputShortPoly": 0,
|
||||||
|
"outputSparseMult": 1.25,
|
||||||
|
"outputTemp": 220,
|
||||||
|
"processName": "Ender 7 PLA",
|
||||||
|
"ranges": [],
|
||||||
|
"sliceAdaptive": false,
|
||||||
|
"sliceAngle": 45,
|
||||||
|
"sliceBottomLayers": 3,
|
||||||
|
"sliceCompInner": 0,
|
||||||
|
"sliceCompOuter": 0,
|
||||||
|
"sliceDetectThin": "basic",
|
||||||
|
"sliceFillAngle": 45,
|
||||||
|
"sliceFillGrow": 0,
|
||||||
|
"sliceFillOverlap": 0.35,
|
||||||
|
"sliceFillRepeat": 1,
|
||||||
|
"sliceFillSparse": 0.25,
|
||||||
|
"sliceFillType": "hex",
|
||||||
|
"sliceFillWidth": 1,
|
||||||
|
"sliceHeight": 0.25,
|
||||||
|
"sliceLayerStart": "last",
|
||||||
|
"sliceLayerStartX": 0,
|
||||||
|
"sliceLayerStartY": 0,
|
||||||
|
"sliceLineWidth": 0,
|
||||||
|
"sliceMinHeight": 0,
|
||||||
|
"sliceShellOrder": "in-out",
|
||||||
|
"sliceShells": 3,
|
||||||
|
"sliceSolidMinArea": 1,
|
||||||
|
"sliceSupportAngle": 50,
|
||||||
|
"sliceSupportArea": 0.1,
|
||||||
|
"sliceSupportDensity": 0.1,
|
||||||
|
"sliceSupportEnable": true,
|
||||||
|
"sliceSupportExtra": 0,
|
||||||
|
"sliceSupportGap": 1,
|
||||||
|
"sliceSupportGrow": 0,
|
||||||
|
"sliceSupportNozzle": 0,
|
||||||
|
"sliceSupportOffset": 1,
|
||||||
|
"sliceSupportOutline": true,
|
||||||
|
"sliceSupportSize": 5,
|
||||||
|
"sliceSupportSpan": 5,
|
||||||
|
"sliceTopLayers": 3,
|
||||||
|
"sliceZInterleave": false,
|
||||||
|
"zHopDistance": 0.2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extras": {}
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,9 @@ import { CAM } from "./driver-fe.js";
|
||||||
import { clearPops, env } from "./client.js";
|
import { clearPops, env } from "./client.js";
|
||||||
|
|
||||||
let alert, lastWidget;
|
let alert, lastWidget;
|
||||||
|
|
||||||
export let helicalOn = false;
|
export let helicalOn = false;
|
||||||
|
|
||||||
export function selectHelical() {
|
export function selectHelical() {
|
||||||
if (helicalOn) {
|
if (helicalOn) {
|
||||||
return helicalDone();
|
return helicalDone();
|
||||||
|
|
@ -25,6 +27,7 @@ export function selectHelical() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
helicalOn = env.hoveredOp;
|
helicalOn = env.hoveredOp;
|
||||||
helicalOn.classList.add("editing");
|
helicalOn.classList.add("editing");
|
||||||
api.feature.on_mouse_up = (obj, ev) => {
|
api.feature.on_mouse_up = (obj, ev) => {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,9 @@ const { MODES } = api.const;
|
||||||
const { uc: UC } = api;
|
const { uc: UC } = api;
|
||||||
const { alerts, conf } = api;
|
const { alerts, conf } = api;
|
||||||
const { current: LANG } = api.language;
|
const { current: LANG } = api.language;
|
||||||
|
const { toInt, toFloat } = UC;
|
||||||
|
|
||||||
|
const units = true;
|
||||||
let seed = Date.now();
|
let seed = Date.now();
|
||||||
|
|
||||||
function hasIndexing() {
|
function hasIndexing() {
|
||||||
|
|
@ -205,12 +207,12 @@ export function createPopOps() {
|
||||||
}).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" }),
|
||||||
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: toInt, show: hasSpindle }),
|
||||||
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 1.0) }),
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: toFloat, bound: UC.bound(0.01, 1.0) }),
|
||||||
stepz: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true, bound: UC.bound(0, 100.0) }),
|
stepz: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: toFloat, units, bound: UC.bound(0, 100.0) }),
|
||||||
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: toInt, units }),
|
||||||
down: UC.newInput(LANG.cc_loff_s, { title: LANG.cc_loff_l, convert: UC.toFloat, units: true }),
|
down: UC.newInput(LANG.cc_loff_s, { title: LANG.cc_loff_l, convert: toFloat, units }),
|
||||||
inset: UC.newInput(LANG.cc_lxyo_s, { title: LANG.cc_lxyo_l, convert: UC.toFloat, units: true, show: () => !env.popOp.level.rec.stock }),
|
inset: UC.newInput(LANG.cc_lxyo_s, { title: LANG.cc_lxyo_l, convert: toFloat, units, show: () => !env.popOp.level.rec.stock }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
stock: UC.newBoolean(LANG.cc_lsto_s, undefined, { title: LANG.cc_lsto_l }),
|
stock: UC.newBoolean(LANG.cc_lsto_s, undefined, { title: LANG.cc_lsto_l }),
|
||||||
};
|
};
|
||||||
|
|
@ -235,14 +237,14 @@ export function createPopOps() {
|
||||||
}).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" }),
|
||||||
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: toInt, show: hasSpindle }),
|
||||||
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: toInt, units }),
|
||||||
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: toInt, units }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true }),
|
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: toFloat, units }),
|
||||||
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 1.0) }),
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: toFloat, bound: UC.bound(0.01, 1.0) }),
|
||||||
leave: UC.newInput(LANG.cr_lsto_s, { title: LANG.cr_lsto_l, convert: UC.toFloat, units: true }),
|
leave: UC.newInput(LANG.cr_lsto_s, { title: LANG.cr_lsto_l, convert: toFloat, units }),
|
||||||
leavez: UC.newInput(LANG.cr_lstz_s, { title: LANG.cr_lstz_l, convert: UC.toFloat, bound: UC.bound(0, 10), units: true }),
|
leavez: UC.newInput(LANG.cr_lstz_s, { title: LANG.cr_lstz_l, convert: toFloat, bound: UC.bound(0, 10), units }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
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 }),
|
||||||
|
|
@ -251,8 +253,8 @@ export function createPopOps() {
|
||||||
omitthru: UC.newBoolean(LANG.co_omit_s, undefined, { title: LANG.co_omit_l }),
|
omitthru: UC.newBoolean(LANG.co_omit_s, undefined, { title: LANG.co_omit_l }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
exp: UC.newExpand("overrides"),
|
exp: UC.newExpand("overrides"),
|
||||||
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: UC.toFloat, units: true }),
|
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: toFloat, units }),
|
||||||
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: UC.toFloat, units: true }),
|
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: toFloat, units }),
|
||||||
ov_conv: UC.newBoolean(LANG.ou_conv_s, undefined, { title: LANG.ou_conv_l }),
|
ov_conv: UC.newBoolean(LANG.ou_conv_s, undefined, { title: LANG.ou_conv_l }),
|
||||||
exp_end: UC.endExpand(),
|
exp_end: UC.endExpand(),
|
||||||
};
|
};
|
||||||
|
|
@ -278,12 +280,12 @@ export function createPopOps() {
|
||||||
}).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" }),
|
||||||
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: toInt, show: hasSpindle }),
|
||||||
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: toInt, units }),
|
||||||
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: toInt, units }),
|
||||||
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true }),
|
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: toFloat, units }),
|
||||||
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 1.0), show: () => env.popOp.outline.rec.wide }),
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: toFloat, bound: UC.bound(0.01, 1.0), show: () => env.popOp.outline.rec.wide }),
|
||||||
steps: UC.newInput(LANG.cc_sovc_s, { title: LANG.cc_sovc_l, convert: UC.toInt, bound: UC.bound(1, 500), show: () => env.popOp.outline.rec.wide }),
|
steps: UC.newInput(LANG.cc_sovc_s, { title: LANG.cc_sovc_l, convert: toInt, bound: UC.bound(1, 500), show: () => env.popOp.outline.rec.wide }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
top: UC.newBoolean(LANG.co_clrt_s, undefined, { title: LANG.co_clrt_l }),
|
top: UC.newBoolean(LANG.co_clrt_s, undefined, { title: LANG.co_clrt_l }),
|
||||||
inside: UC.newBoolean(LANG.co_olin_s, undefined, { title: LANG.co_olin_l, show: (op) => { return !op.inputs.outside.checked } }),
|
inside: UC.newBoolean(LANG.co_olin_s, undefined, { title: LANG.co_olin_l, show: (op) => { return !op.inputs.outside.checked } }),
|
||||||
|
|
@ -295,8 +297,8 @@ export function createPopOps() {
|
||||||
dogbones: UC.newBoolean(LANG.co_dogb_s, undefined, { title: LANG.co_dogb_l, show: (op) => { return !op.inputs.wide.checked } }),
|
dogbones: UC.newBoolean(LANG.co_dogb_s, undefined, { title: LANG.co_dogb_l, show: (op) => { return !op.inputs.wide.checked } }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
exp: UC.newExpand("overrides"),
|
exp: UC.newExpand("overrides"),
|
||||||
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: UC.toFloat, units: true }),
|
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: toFloat, units }),
|
||||||
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: UC.toFloat, units: true }),
|
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: toFloat, units }),
|
||||||
ov_conv: UC.newBoolean(LANG.ou_conv_s, undefined, { title: LANG.ou_conv_l }),
|
ov_conv: UC.newBoolean(LANG.ou_conv_s, undefined, { title: LANG.ou_conv_l }),
|
||||||
exp_end: UC.endExpand(),
|
exp_end: UC.endExpand(),
|
||||||
};
|
};
|
||||||
|
|
@ -323,17 +325,17 @@ export function createPopOps() {
|
||||||
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
axis: UC.newSelect(LANG.cd_axis, {}, "xyaxis"),
|
axis: UC.newSelect(LANG.cd_axis, {}, "xyaxis"),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: toInt, show: hasSpindle }),
|
||||||
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: toInt, units }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 10.0) }),
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: toFloat, bound: UC.bound(0.01, 10.0) }),
|
||||||
leave: UC.newInput(LANG.cf_leav_s, { title: LANG.cf_leav_l, convert: UC.toFloat, bound: UC.bound(0, 100) }),
|
leave: UC.newInput(LANG.cf_leav_s, { title: LANG.cf_leav_l, convert: toFloat, bound: UC.bound(0, 100) }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
angle: UC.newInput(LANG.cf_angl_s, { title: LANG.cf_angl_l, convert: UC.toFloat, bound: UC.bound(45, 90), show: (op) => op.inputs.curves.checked }),
|
angle: UC.newInput(LANG.cf_angl_s, { title: LANG.cf_angl_l, convert: toFloat, bound: UC.bound(45, 90), show: (op) => op.inputs.curves.checked }),
|
||||||
flatness: UC.newInput(LANG.ou_flat_s, { title: LANG.ou_flat_l, convert: UC.toFloat, bound: UC.bound(0, 1.0), units: false, round: 4 }),
|
flatness: UC.newInput(LANG.ou_flat_s, { title: LANG.ou_flat_l, convert: toFloat, bound: UC.bound(0, 1.0), units: false, round: 4 }),
|
||||||
tolerance: UC.newInput(LANG.ou_toll_s, { title: LANG.ou_toll_l, convert: UC.toFloat, bound: UC.bound(0, 10.0), units: true, round: 4 }),
|
tolerance: UC.newInput(LANG.ou_toll_s, { title: LANG.ou_toll_l, convert: toFloat, bound: UC.bound(0, 10.0), units, round: 4 }),
|
||||||
reduction: UC.newInput(LANG.ou_redu_s, { title: LANG.ou_redu_l, convert: UC.toInt, bound: UC.bound(0, 10), units: false }),
|
reduction: UC.newInput(LANG.ou_redu_s, { title: LANG.ou_redu_l, convert: toInt, bound: UC.bound(0, 10), units: false }),
|
||||||
// bridging: UC.newInput(LANG.ou_brdg_s, {title:LANG.ou_brdg_l, convert:UC.toFloat, bound:UC.bound(0,1000.0), units:true, round:4, show:(op) => op.inputs.curves.checked}),
|
// bridging: UC.newInput(LANG.ou_brdg_s, {title:LANG.ou_brdg_l, convert:toFloat, bound:UC.bound(0,1000.0), units:true, round:4, show:(op) => op.inputs.curves.checked}),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
curves: UC.newBoolean(LANG.cf_curv_s, undefined, { title: LANG.cf_curv_l }),
|
curves: UC.newBoolean(LANG.cf_curv_s, undefined, { title: LANG.cf_curv_l }),
|
||||||
inside: UC.newBoolean(LANG.cf_olin_s, undefined, { title: LANG.cf_olin_l }),
|
inside: UC.newBoolean(LANG.cf_olin_s, undefined, { title: LANG.cf_olin_l }),
|
||||||
|
|
@ -357,17 +359,17 @@ export function createPopOps() {
|
||||||
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
// axis: UC.newSelect(LANG.cd_axis, {}, "xyaxis"),
|
// axis: UC.newSelect(LANG.cd_axis, {}, "xyaxis"),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: toInt, show: hasSpindle }),
|
||||||
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: toInt, units }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 100.0) }),
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: toFloat, bound: UC.bound(0.01, 100.0) }),
|
||||||
angle: UC.newInput(LANG.cc_sang_s, { title: LANG.cc_sang_l, convert: UC.toFloat, bound: UC.bound(0.01, 180.0) }),
|
angle: UC.newInput(LANG.cc_sang_s, { title: LANG.cc_sang_l, convert: toFloat, bound: UC.bound(0.01, 180.0) }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
offStart: UC.newInput(LANG.ci_laso_s, { title: LANG.ci_laso_l, convert: UC.toFloat}),
|
offStart: UC.newInput(LANG.ci_laso_s, { title: LANG.ci_laso_l, convert: toFloat}),
|
||||||
offEnd: UC.newInput(LANG.ci_laeo_s, { title: LANG.ci_laeo_l, convert: UC.toFloat}),
|
offEnd: UC.newInput(LANG.ci_laeo_s, { title: LANG.ci_laeo_l, convert: toFloat}),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
tolerance: UC.newInput(LANG.ou_toll_s, { title: LANG.ou_toll_l, convert: UC.toFloat, bound: UC.bound(0, 10.0), units: true, round: 4 }),
|
tolerance: UC.newInput(LANG.ou_toll_s, { title: LANG.ou_toll_l, convert: toFloat, bound: UC.bound(0, 10.0), units, round: 4 }),
|
||||||
leave: UC.newInput(LANG.cf_leav_s, { title: LANG.cf_leav_l, convert: UC.toFloat, bound: UC.bound(0, 100) }),
|
leave: UC.newInput(LANG.cf_leav_s, { title: LANG.cf_leav_l, convert: toFloat, bound: UC.bound(0, 100) }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
linear: UC.newBoolean(LANG.ci_line_s, undefined, { title: LANG.ci_line_l }),
|
linear: UC.newBoolean(LANG.ci_line_s, undefined, { title: LANG.ci_line_l }),
|
||||||
// filter: UC.newRow([ UC.newButton(LANG.filter, contourFilter) ], {class:"ext-buttons f-row"})
|
// filter: UC.newRow([ UC.newButton(LANG.filter, contourFilter) ], {class:"ext-buttons f-row"})
|
||||||
|
|
@ -408,22 +410,22 @@ export function createPopOps() {
|
||||||
mode: UC.newSelect(LANG.cu_type_s, { title: LANG.cu_type_l }, "trace"),
|
mode: UC.newSelect(LANG.cu_type_s, { title: LANG.cu_type_l }, "trace"),
|
||||||
offset: UC.newSelect(LANG.cc_offs_s, { title: LANG.cc_offs_l, show: () => (env.poppedRec.mode === 'follow') }, "traceoff"),
|
offset: UC.newSelect(LANG.cc_offs_s, { title: LANG.cc_offs_l, show: () => (env.poppedRec.mode === 'follow') }, "traceoff"),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: toInt, show: hasSpindle }),
|
||||||
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: toInt, units }),
|
||||||
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: toInt, units }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 1.0), show: (op) => env.popOp.trace.rec.mode === "clear" }),
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: toFloat, bound: UC.bound(0.01, 1.0), show: (op) => env.popOp.trace.rec.mode === "clear" }),
|
||||||
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true }),
|
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: toFloat, units }),
|
||||||
thru: UC.newInput(LANG.cc_thru_s, { title: LANG.cc_thru_l, convert: UC.toFloat, units: true }),
|
thru: UC.newInput(LANG.cc_thru_s, { title: LANG.cc_thru_l, convert: toFloat, units }),
|
||||||
offover: UC.newInput(LANG.cc_offd_s, { title: LANG.cc_offd_l, convert: UC.toFloat, units: true, show: () => env.poppedRec.offset !== "none" || env.poppedRec.mode === "clear" }),
|
offover: UC.newInput(LANG.cc_offd_s, { title: LANG.cc_offd_l, convert: toFloat, units, show: () => env.poppedRec.offset !== "none" || env.poppedRec.mode === "clear" }),
|
||||||
sep: UC.newBlank({ class: "pop-sep", modes: MODES.CAM, xshow: zDogSep }),
|
sep: UC.newBlank({ class: "pop-sep", modes: MODES.CAM, xshow: zDogSep }),
|
||||||
merge: UC.newBoolean(LANG.co_merg_s, undefined, { title: LANG.co_merg_l, show: () => !env.popOp.trace.rec.down }),
|
merge: UC.newBoolean(LANG.co_merg_s, undefined, { title: LANG.co_merg_l, show: () => !env.popOp.trace.rec.down }),
|
||||||
dogbone: UC.newBoolean(LANG.co_dogb_s, undefined, { title: LANG.co_dogb_l, show: canDogBones }),
|
dogbone: UC.newBoolean(LANG.co_dogb_s, undefined, { title: LANG.co_dogb_l, show: canDogBones }),
|
||||||
revbone: UC.newBoolean(LANG.co_dogr_s, undefined, { title: LANG.co_dogr_l, show: canDogBonesRev }),
|
revbone: UC.newBoolean(LANG.co_dogr_s, undefined, { title: LANG.co_dogr_l, show: canDogBonesRev }),
|
||||||
exp: UC.newExpand("overrides"),
|
exp: UC.newExpand("overrides"),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: UC.toFloat, units: true }),
|
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: toFloat, units }),
|
||||||
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: UC.toFloat, units: true }),
|
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: toFloat, units }),
|
||||||
ov_conv: UC.newBoolean(LANG.ou_conv_s, undefined, { title: LANG.ou_conv_l }),
|
ov_conv: UC.newBoolean(LANG.ou_conv_s, undefined, { title: LANG.ou_conv_l }),
|
||||||
exp_end: UC.endExpand(),
|
exp_end: UC.endExpand(),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
|
@ -451,26 +453,26 @@ export function createPopOps() {
|
||||||
}).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" }),
|
||||||
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: toInt, show: hasSpindle }),
|
||||||
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: toInt, units }),
|
||||||
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: toInt, units }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: UC.toFloat, bound: UC.bound(0.01, 1.0) }),
|
step: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: toFloat, bound: UC.bound(0.01, 1.0) }),
|
||||||
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true, show: () => !env.poppedRec.contour }),
|
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: toFloat, units, show: () => !env.poppedRec.contour }),
|
||||||
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, xshow: () => !env.poppedRec.contour }),
|
expand: UC.newInput(LANG.cp_xpnd_s, { title: LANG.cp_xpnd_l, convert: toFloat, units, xshow: () => !env.poppedRec.contour }),
|
||||||
refine: UC.newInput(LANG.cp_refi_s, { title: LANG.cp_refi_l, convert: UC.toInt, show: () => env.poppedRec.contour }),
|
refine: UC.newInput(LANG.cp_refi_s, { title: LANG.cp_refi_l, convert: toInt, show: () => env.poppedRec.contour }),
|
||||||
smooth: UC.newInput(LANG.cp_smoo_s, { title: LANG.cp_smoo_l, convert: UC.toInt }),
|
smooth: UC.newInput(LANG.cp_smoo_s, { title: LANG.cp_smoo_l, convert: toInt }),
|
||||||
tolerance: UC.newInput(LANG.ou_toll_s, { title: LANG.ou_toll_l, convert: UC.toFloat, bound: UC.bound(0, 10.0), units: true, round: 4, show: () => env.poppedRec.contour }),
|
tolerance: UC.newInput(LANG.ou_toll_s, { title: LANG.ou_toll_l, convert: toFloat, bound: UC.bound(0, 10.0), units, round: 4, show: () => env.poppedRec.contour }),
|
||||||
follow: UC.newInput(LANG.cp_foll_s, { title: LANG.cp_foll_l, convert: UC.toFloat }),
|
follow: UC.newInput(LANG.cp_foll_s, { title: LANG.cp_foll_l, convert: toFloat }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
contour: UC.newBoolean(LANG.cp_cont_s, undefined, { title: LANG.cp_cont_s }),
|
contour: UC.newBoolean(LANG.cp_cont_s, undefined, { title: LANG.cp_cont_s }),
|
||||||
engrave: UC.newBoolean(LANG.cp_engr_s, undefined, { title: LANG.cp_engr_l, show: () => env.poppedRec.contour }),
|
engrave: UC.newBoolean(LANG.cp_engr_s, undefined, { title: LANG.cp_engr_l, show: () => env.poppedRec.contour }),
|
||||||
outline: UC.newBoolean(LANG.cp_outl_s, undefined, { title: LANG.cp_outl_l }),
|
outline: UC.newBoolean(LANG.cp_outl_s, undefined, { title: LANG.cp_outl_l }),
|
||||||
exp: UC.newExpand("overrides"),
|
exp: UC.newExpand("overrides"),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: UC.toFloat, units: true }),
|
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: toFloat, units }),
|
||||||
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: UC.toFloat, units: true }),
|
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: toFloat, units }),
|
||||||
ov_conv: UC.newBoolean(LANG.ou_conv_s, undefined, { title: LANG.ou_conv_l }),
|
ov_conv: UC.newBoolean(LANG.ou_conv_s, undefined, { title: LANG.ou_conv_l }),
|
||||||
exp_end: UC.endExpand(),
|
exp_end: UC.endExpand(),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
|
@ -491,16 +493,16 @@ export function createPopOps() {
|
||||||
}).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" }),
|
||||||
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: UC.toInt, show: hasSpindle }),
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: toInt, show: hasSpindle }),
|
||||||
rate: UC.newInput(LANG.cc_plng_s, { title: LANG.cc_plng_l, convert: UC.toInt, units: true }),
|
rate: UC.newInput(LANG.cc_plng_s, { title: LANG.cc_plng_l, convert: toInt, units }),
|
||||||
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: UC.toFloat, units: true }),
|
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: toFloat, units }),
|
||||||
dwell: UC.newInput(LANG.cd_dwll_s, { title: LANG.cd_dwll_l, convert: UC.toFloat }),
|
dwell: UC.newInput(LANG.cd_dwll_s, { title: LANG.cd_dwll_l, convert: toFloat }),
|
||||||
lift: UC.newInput(LANG.cd_lift_s, { title: LANG.cd_lift_l, convert: UC.toFloat, units: true, show: () => !env.poppedRec.mark }),
|
lift: UC.newInput(LANG.cd_lift_s, { title: LANG.cd_lift_l, convert: toFloat, units, show: () => !env.poppedRec.mark }),
|
||||||
mark: UC.newBoolean(LANG.cd_mark_s, undefined, { title: LANG.cd_mark_l, show: () => !env.poppedRec.fromTop }),
|
mark: UC.newBoolean(LANG.cd_mark_s, undefined, { title: LANG.cd_mark_l, show: () => !env.poppedRec.fromTop }),
|
||||||
fromTop: UC.newBoolean(LANG.cd_ftop_s, undefined, { title: LANG.cd_ftop_l, show: () => !env.poppedRec.mark }),
|
fromTop: UC.newBoolean(LANG.cd_ftop_s, undefined, { title: LANG.cd_ftop_l, show: () => !env.poppedRec.mark }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
thru: UC.newInput(LANG.cd_dtru_s, { title: LANG.cd_dtru_l, convert: UC.toFloat, units: true, show: () => !env.poppedRec.mark }),
|
thru: UC.newInput(LANG.cd_dtru_s, { title: LANG.cd_dtru_l, convert: toFloat, units, show: () => !env.poppedRec.mark }),
|
||||||
precision: UC.newInput(LANG.cd_prcn_s, { title: LANG.cd_prcn_l, convert: UC.toFloat, units: true, show: () => !env.poppedRec.mark }),
|
precision: UC.newInput(LANG.cd_prcn_s, { title: LANG.cd_prcn_l, convert: toFloat, units, show: () => !env.poppedRec.mark }),
|
||||||
sep: UC.newBlank({ class: "pop-sep", }),
|
sep: UC.newBlank({ class: "pop-sep", }),
|
||||||
actions: UC.newRow([
|
actions: UC.newRow([
|
||||||
UC.newButton(LANG.select, () => selectHoles(true), { title: LANG.cd_seli_l }),
|
UC.newButton(LANG.select, () => selectHoles(true), { title: LANG.cd_seli_l }),
|
||||||
|
|
@ -523,16 +525,16 @@ export function createPopOps() {
|
||||||
axis: UC.newSelect(LANG.cd_axis, {}, "regaxis"),
|
axis: UC.newSelect(LANG.cd_axis, {}, "regaxis"),
|
||||||
points: UC.newSelect(LANG.cd_points, {show:() => env.poppedRec.axis !== '-'}, "regpoints"),
|
points: UC.newSelect(LANG.cd_points, {show:() => env.poppedRec.axis !== '-'}, "regpoints"),
|
||||||
sep: UC.newBlank({class:"pop-sep"}),
|
sep: UC.newBlank({class:"pop-sep"}),
|
||||||
spindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:UC.toInt, show:hasSpindle}),
|
spindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:toInt, show:hasSpindle}),
|
||||||
rate: UC.newInput(LANG.cc_plng_s, {title:LANG.cc_plng_l, convert:UC.toInt, units:true}),
|
rate: UC.newInput(LANG.cc_plng_s, {title:LANG.cc_plng_l, convert:toInt, units:true}),
|
||||||
feed: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:UC.toInt, units:true, show:() => env.poppedRec.axis === '-'}),
|
feed: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:toInt, units:true, show:() => env.poppedRec.axis === '-'}),
|
||||||
sep: UC.newBlank({class:"pop-sep"}),
|
sep: UC.newBlank({class:"pop-sep"}),
|
||||||
down: UC.newInput(LANG.cc_sdwn_s, {title:LANG.cc_sdwn_l, convert:UC.toFloat, units:true}),
|
down: UC.newInput(LANG.cc_sdwn_s, {title:LANG.cc_sdwn_l, convert:toFloat, units:true}),
|
||||||
dwell: UC.newInput(LANG.cd_dwll_s, {title:LANG.cd_dwll_l, convert:UC.toFloat, show:() => env.poppedRec.axis !== '-'}),
|
dwell: UC.newInput(LANG.cd_dwll_s, {title:LANG.cd_dwll_l, convert:toFloat, show:() => env.poppedRec.axis !== '-'}),
|
||||||
lift: UC.newInput(LANG.cd_lift_s, {title:LANG.cd_lift_l, convert:UC.toFloat, units:true, show:() => env.poppedRec.axis !== '-'}),
|
lift: UC.newInput(LANG.cd_lift_s, {title:LANG.cd_lift_l, convert:toFloat, units:true, show:() => env.poppedRec.axis !== '-'}),
|
||||||
sep: UC.newBlank({class:"pop-sep"}),
|
sep: UC.newBlank({class:"pop-sep"}),
|
||||||
offset: UC.newInput(LANG.cd_rego_s, {title:LANG.cd_rego_l, convert:UC.toFloat, units:true, }),
|
offset: UC.newInput(LANG.cd_rego_s, {title:LANG.cd_rego_l, convert:toFloat, units:true, }),
|
||||||
thru: UC.newInput(LANG.cd_thru_s, {title:LANG.cd_thru_l, convert:UC.toFloat, units:true}),
|
thru: UC.newInput(LANG.cd_thru_s, {title:LANG.cd_thru_l, convert:toFloat, units:true}),
|
||||||
};
|
};
|
||||||
|
|
||||||
createPopOp('helical', {
|
createPopOp('helical', {
|
||||||
|
|
@ -556,15 +558,15 @@ export function createPopOps() {
|
||||||
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
offset: UC.newSelect(LANG.cc_offs_s, {title: LANG.cc_offs_l,}, "helicaloff"),
|
offset: UC.newSelect(LANG.cc_offs_s, {title: LANG.cc_offs_l,}, "helicaloff"),
|
||||||
sep: UC.newBlank({class:"pop-sep"}),
|
sep: UC.newBlank({class:"pop-sep"}),
|
||||||
spindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:UC.toInt, show:hasSpindle}),
|
spindle: UC.newInput(LANG.cc_spnd_s, {title:LANG.cc_spnd_l, convert:toInt, show:hasSpindle}),
|
||||||
rate: UC.newInput(LANG.cc_plng_s, {title:LANG.cc_plng_l, convert:UC.toFloat, units:true}),
|
rate: UC.newInput(LANG.cc_plng_s, {title:LANG.cc_plng_l, convert:toFloat, units:true}),
|
||||||
feed: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:UC.toFloat, units:true}),
|
feed: UC.newInput(LANG.cc_feed_s, {title:LANG.cc_feed_l, convert:toFloat, units:true}),
|
||||||
down: UC.newInput(LANG.ch_sdwn_s, {title:LANG.ch_sdwn_l, convert:UC.toFloat, units:true}),
|
down: UC.newInput(LANG.ch_sdwn_s, {title:LANG.ch_sdwn_l, convert:toFloat, units:true}),
|
||||||
startAng: UC.newInput(LANG.ch_stra_s, {title:LANG.ch_stra_l, convert:UC.toDegsFloat, bound:UC.bound(-360,360),show:() => env.poppedRec.forceStartAng}),
|
startAng: UC.newInput(LANG.ch_stra_s, {title:LANG.ch_stra_l, convert:UC.toDegsFloat, bound:UC.bound(-360,360),show:() => env.poppedRec.forceStartAng}),
|
||||||
offOver: UC.newInput(LANG.cc_offd_s, {title:LANG.cc_offd_l, convert:UC.toFloat, units:true, bound:UC.bound(0,Infinity)}),
|
offOver: UC.newInput(LANG.cc_offd_s, {title:LANG.cc_offd_l, convert:toFloat, units:true, bound:UC.bound(0,Infinity)}),
|
||||||
sep: UC.newBlank({class:"pop-sep"}),
|
sep: UC.newBlank({class:"pop-sep"}),
|
||||||
entry: UC.newBoolean(LANG.ch_entr_s,undefined, {title:LANG.ch_entr_l}),
|
entry: UC.newBoolean(LANG.ch_entr_s,undefined, {title:LANG.ch_entr_l}),
|
||||||
entryOffset: UC.newInput(LANG.ch_ento_s, {title:LANG.ch_ento_l, convert:UC.toFloat, units:true, show:() => env.poppedRec.entry}),
|
entryOffset: UC.newInput(LANG.ch_ento_s, {title:LANG.ch_ento_l, convert:toFloat, units:true, show:() => env.poppedRec.entry}),
|
||||||
reverse: UC.newBoolean(LANG.ch_rvrs_s,undefined, {title:LANG.ch_rvrs_l}),
|
reverse: UC.newBoolean(LANG.ch_rvrs_s,undefined, {title:LANG.ch_rvrs_l}),
|
||||||
clockwise:UC.newBoolean(LANG.ch_clkw_s,undefined, {title:LANG.ch_clkw_l}),
|
clockwise:UC.newBoolean(LANG.ch_clkw_s,undefined, {title:LANG.ch_clkw_l}),
|
||||||
sep: UC.newBlank({class:"pop-sep"}),
|
sep: UC.newBlank({class:"pop-sep"}),
|
||||||
|
|
@ -572,7 +574,7 @@ export function createPopOps() {
|
||||||
forceStartAng: UC.newBoolean(LANG.ch_fsta_s, undefined, {title:LANG.ch_fsta_l }),
|
forceStartAng: UC.newBoolean(LANG.ch_fsta_s, undefined, {title:LANG.ch_fsta_l }),
|
||||||
fromTop: UC.newBoolean(LANG.cd_ftop_s,undefined, {title:LANG.cd_ftop_l}),
|
fromTop: UC.newBoolean(LANG.cd_ftop_s,undefined, {title:LANG.cd_ftop_l}),
|
||||||
sep: UC.newBlank({class:"pop-sep"}),
|
sep: UC.newBlank({class:"pop-sep"}),
|
||||||
thru: UC.newInput(LANG.cd_thru_s, {title:LANG.cd_thru_l, convert:UC.toFloat, units:true}),
|
thru: UC.newInput(LANG.cd_thru_s, {title:LANG.cd_thru_l, convert:toFloat, units:true}),
|
||||||
actions: UC.newRow([
|
actions: UC.newRow([
|
||||||
UC.newButton(LANG.select, selectHelical, {title:LANG.cd_seli_l}),
|
UC.newButton(LANG.select, selectHelical, {title:LANG.cd_seli_l}),
|
||||||
], {class:"ext-buttons f-col"})
|
], {class:"ext-buttons f-col"})
|
||||||
|
|
@ -603,7 +605,7 @@ export function createPopOps() {
|
||||||
degrees: 'camIndexAxis',
|
degrees: 'camIndexAxis',
|
||||||
absolute: 'camIndexAbs'
|
absolute: 'camIndexAbs'
|
||||||
}).inputs = {
|
}).inputs = {
|
||||||
degrees: UC.newInput(LANG.ci_degr_s, { title: LANG.ci_degr_l, convert: UC.toFloat, bound: UC.bound(-360, 360.0) }),
|
degrees: UC.newInput(LANG.ci_degr_s, { title: LANG.ci_degr_l, convert: toFloat, bound: UC.bound(-360, 360.0) }),
|
||||||
absolute: UC.newBoolean(LANG.ci_abso_s, undefined, { title: LANG.ci_abso_l }),
|
absolute: UC.newBoolean(LANG.ci_abso_s, undefined, { title: LANG.ci_abso_l }),
|
||||||
select: UC.newRow([UC.newButton(LANG.ci_face_s, angleTowardZUp)], { class: "ext-buttons f-row" })
|
select: UC.newRow([UC.newButton(LANG.ci_face_s, angleTowardZUp)], { class: "ext-buttons f-row" })
|
||||||
};
|
};
|
||||||
|
|
@ -630,12 +632,12 @@ export function createPopOps() {
|
||||||
on: UC.newRow([UC.newButton(LANG.on, editOn)], { class: "ext-buttons f-row" }),
|
on: UC.newRow([UC.newButton(LANG.on, editOn)], { class: "ext-buttons f-row" }),
|
||||||
off: UC.newRow([UC.newButton(LANG.off, editOff)], { class: "ext-buttons f-row" }),
|
off: UC.newRow([UC.newButton(LANG.off, editOff)], { class: "ext-buttons f-row" }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
power: UC.newInput(LANG.cl_powr_s, { title: LANG.cl_powr_l, convert: UC.toFloat, bound: UC.bound(0, 1.0), show: () => !env.poppedRec.adapt }),
|
power: UC.newInput(LANG.cl_powr_s, { title: LANG.cl_powr_l, convert: toFloat, bound: UC.bound(0, 1.0), show: () => !env.poppedRec.adapt }),
|
||||||
maxp: UC.newInput(LANG.cl_maxp_s, { title: LANG.cl_maxp_l, convert: UC.toFloat, bound: UC.bound(0, 1.0), show: () => env.poppedRec.adapt }),
|
maxp: UC.newInput(LANG.cl_maxp_s, { title: LANG.cl_maxp_l, convert: toFloat, bound: UC.bound(0, 1.0), show: () => env.poppedRec.adapt }),
|
||||||
minp: UC.newInput(LANG.cl_minp_s, { title: LANG.cl_minp_l, convert: UC.toFloat, bound: UC.bound(0, 1.0), show: () => env.poppedRec.adapt }),
|
minp: UC.newInput(LANG.cl_minp_s, { title: LANG.cl_minp_l, convert: toFloat, bound: UC.bound(0, 1.0), show: () => env.poppedRec.adapt }),
|
||||||
maxz: UC.newInput(LANG.cl_maxz_s, { title: LANG.cl_maxz_l, convert: UC.toFloat, show: () => env.poppedRec.adapt }),
|
maxz: UC.newInput(LANG.cl_maxz_s, { title: LANG.cl_maxz_l, convert: toFloat, show: () => env.poppedRec.adapt }),
|
||||||
minz: UC.newInput(LANG.cl_minz_s, { title: LANG.cl_minz_l, convert: UC.toFloat, show: () => env.poppedRec.adapt }),
|
minz: UC.newInput(LANG.cl_minz_s, { title: LANG.cl_minz_l, convert: toFloat, show: () => env.poppedRec.adapt }),
|
||||||
flatz: UC.newInput(LANG.cl_flaz_s, { title: LANG.cl_flaz_l, convert: UC.toFloat, show: () => env.poppedRec.flat }),
|
flatz: UC.newInput(LANG.cl_flaz_s, { title: LANG.cl_flaz_l, convert: toFloat, show: () => env.poppedRec.flat }),
|
||||||
sep: UC.newBlank({ class: "pop-sep" }),
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
adapt: UC.newBoolean(LANG.cl_adap_s, undefined, { title: LANG.cl_adap_l }),
|
adapt: UC.newBoolean(LANG.cl_adap_s, undefined, { title: LANG.cl_adap_l }),
|
||||||
adaptrp: UC.newBoolean(LANG.cl_adrp_s, undefined, { title: LANG.cl_adrp_l, show: () => env.poppedRec.adapt }),
|
adaptrp: UC.newBoolean(LANG.cl_adrp_s, undefined, { title: LANG.cl_adrp_l, show: () => env.poppedRec.adapt }),
|
||||||
|
|
@ -651,4 +653,75 @@ export function createPopOps() {
|
||||||
};
|
};
|
||||||
|
|
||||||
createPopOp('|', {}).inputs = {};
|
createPopOp('|', {}).inputs = {};
|
||||||
|
|
||||||
|
function isClear() {
|
||||||
|
return env.poppedRec.mode === 'clear';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTrace() {
|
||||||
|
return env.poppedRec.mode === 'trace';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSurface() {
|
||||||
|
return env.poppedRec.mode === 'surface';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSurfaceLinear() {
|
||||||
|
return env.poppedRec.mode === 'surface' && env.poppedRec.sr_type === 'linear';
|
||||||
|
}
|
||||||
|
|
||||||
|
createPopOp('area', {
|
||||||
|
spindle: 'camAreaSpindle',
|
||||||
|
tool: 'camAreaTool',
|
||||||
|
mode: 'camAreaMode',
|
||||||
|
tr_type: 'camAreaTrace',
|
||||||
|
sr_type: 'camAreaSurface',
|
||||||
|
sr_angle: 'camAreaAngle',
|
||||||
|
over: 'camAreaOver',
|
||||||
|
down: 'camAreaDown',
|
||||||
|
rate: 'camAreaSpeed',
|
||||||
|
plunge: 'camAreaPlunge',
|
||||||
|
expand: 'camAreaExpand',
|
||||||
|
smooth: 'camAreaSmooth',
|
||||||
|
refine: 'camAreaRefine',
|
||||||
|
outline: 'camAreaOutline',
|
||||||
|
ov_topz: 0,
|
||||||
|
ov_botz: 0,
|
||||||
|
ov_conv: '~camConventional',
|
||||||
|
tolerance: 'camTolerance',
|
||||||
|
}).inputs = {
|
||||||
|
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||||
|
mode: UC.newSelect(LANG.mo_menu, {}, "opmode"),
|
||||||
|
tr_type: UC.newSelect(LANG.cc_offs_s, { title: LANG.cc_offs_l, show: isTrace }, "traceoff"),
|
||||||
|
sr_type: UC.newSelect("pattern", { title: "pattern", show: isSurface }, "surftyp"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
menu: UC.newRow([
|
||||||
|
UC.newButton("edge", traceAdd),
|
||||||
|
UC.newButton("surface", surfaceAdd),
|
||||||
|
], { class: "ext-buttons f-row" }),
|
||||||
|
outline: UC.newBoolean(LANG.cp_outl_s, undefined, { title: LANG.cp_outl_l }),
|
||||||
|
expand: UC.newInput(LANG.cp_xpnd_s, { title: LANG.cp_xpnd_l, convert: toFloat, units }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
sr_angle: UC.newInput("step angle", { title: "step angle", convert: toFloat, bound: UC.bound(0, 360), show: isSurfaceLinear }),
|
||||||
|
over: UC.newInput(LANG.cc_sovr_s, { title: LANG.cc_sovr_l, convert: toFloat, bound: UC.bound(0.001, 100.0), show: () => isClear() || isSurface() }),
|
||||||
|
down: UC.newInput(LANG.cc_sdwn_s, { title: LANG.cc_sdwn_l, convert: toFloat, bound: UC.bound(0, 100.0), units, show: () => isClear() || isTrace() }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep", show: isSurface }),
|
||||||
|
refine: UC.newInput(LANG.cp_refi_s, { title: LANG.cp_refi_l, convert: toInt, show: isSurface }),
|
||||||
|
smooth: UC.newInput(LANG.cp_smoo_s, { title: LANG.cp_smoo_l, convert: toInt, show: isSurface }),
|
||||||
|
tolerance: UC.newInput(LANG.ou_toll_s, { title: LANG.ou_toll_l, convert: toFloat, bound: UC.bound(0, 10.0), units, round: 4, show: isSurface }),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
exp: UC.newExpand("feeds & speeds"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
spindle: UC.newInput(LANG.cc_spnd_s, { title: LANG.cc_spnd_l, convert: toInt, show: hasSpindle }),
|
||||||
|
rate: UC.newInput(LANG.cc_feed_s, { title: LANG.cc_feed_l, convert: toInt, units }),
|
||||||
|
plunge: UC.newInput(LANG.cc_plng_s, { title: LANG.cc_plng_l, convert: toInt, units }),
|
||||||
|
exp_end: UC.endExpand(),
|
||||||
|
exp: UC.newExpand("overrides"),
|
||||||
|
sep: UC.newBlank({ class: "pop-sep" }),
|
||||||
|
ov_topz: UC.newInput(LANG.ou_ztop_s, { title: LANG.ou_ztop_l, convert: toFloat, units }),
|
||||||
|
ov_botz: UC.newInput(LANG.ou_zbot_s, { title: LANG.ou_zbot_l, convert: toFloat, units }),
|
||||||
|
ov_conv: UC.newBoolean(LANG.ou_conv_s, undefined, { title: LANG.ou_conv_l }),
|
||||||
|
exp_end: UC.endExpand(),
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,10 @@ export function surfaceAdd(ev) {
|
||||||
return surfaceDone();
|
return surfaceDone();
|
||||||
}
|
}
|
||||||
clearPops();
|
clearPops();
|
||||||
|
let { surfaces, follow } = env.poppedRec;
|
||||||
|
let { edgeangle } = api.conf.get().controller;
|
||||||
alert = api.show.alert("analyzing surfaces...", 1000);
|
alert = api.show.alert("analyzing surfaces...", 1000);
|
||||||
let surfaces = env.poppedRec.surfaces;
|
let radians = (follow ?? edgeangle) * DEG2RAD;
|
||||||
let radians = env.poppedRec.follow * DEG2RAD;
|
|
||||||
CAM.surface_prep(env.currentIndex * RAD2DEG, () => {
|
CAM.surface_prep(env.currentIndex * RAD2DEG, () => {
|
||||||
api.hide.alert(alert);
|
api.hide.alert(alert);
|
||||||
alert = api.show.alert("[esc] cancels surface selection");
|
alert = api.show.alert("[esc] cancels surface selection");
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,12 @@ export function addWidgetTab(widget, rec) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function recreateTabs() {
|
||||||
|
let widgets = api.widgets.all();
|
||||||
|
for (let w of widgets) clearTabs(w, true);
|
||||||
|
restoreTabs(widgets);
|
||||||
|
}
|
||||||
|
|
||||||
export function restoreTabs(widgets) {
|
export function restoreTabs(widgets) {
|
||||||
widgets.forEach(widget => {
|
widgets.forEach(widget => {
|
||||||
const tabs = api.widgets.annotate(widget.id).tab || [];
|
const tabs = api.widgets.annotate(widget.id).tab || [];
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,11 @@ import { holeSelOn, selectHolesDone, clearHolesRec } from './cl-hole.js';
|
||||||
import { surfaceOn, surfaceDone } from './cl-surface.js';
|
import { surfaceOn, surfaceDone } from './cl-surface.js';
|
||||||
import { helicalOn, helicalDone } from './cl-helical.js';
|
import { helicalOn, helicalDone } from './cl-helical.js';
|
||||||
import { originSelectDone } from './cl-origin.js';
|
import { originSelectDone } from './cl-origin.js';
|
||||||
|
import { Widget, newWidget } from '../../core/widget.js';
|
||||||
|
import { space } from '../../../moto/space.js';
|
||||||
|
import { recreateTabs } from './cl-tab.js';
|
||||||
|
|
||||||
|
const { BufferGeometryUtils } = THREE;
|
||||||
|
|
||||||
const DEG2RAD = Math.PI / 180;
|
const DEG2RAD = Math.PI / 180;
|
||||||
const RAD2DEG = 180 / Math.PI;
|
const RAD2DEG = 180 / Math.PI;
|
||||||
|
|
@ -184,6 +189,15 @@ const opAddHelical = () => {
|
||||||
opAdd(rec);
|
opAdd(rec);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const opAddArea = () => {
|
||||||
|
traceDone();
|
||||||
|
surfaceDone();
|
||||||
|
let rec = env.popOp.area.new();
|
||||||
|
rec.areas = { /* widget.id: [ polygons... ] */ };
|
||||||
|
rec.surfaces = { /* widget.id: [ faces... ] */ };
|
||||||
|
opAdd(rec);
|
||||||
|
};
|
||||||
|
|
||||||
const opAddContour = (axis) => {
|
const opAddContour = (axis) => {
|
||||||
let rec = env.popOp.contour.new();
|
let rec = env.popOp.contour.new();
|
||||||
rec.axis = axis.toUpperCase();
|
rec.axis = axis.toUpperCase();
|
||||||
|
|
@ -273,7 +287,7 @@ export function opRender() {
|
||||||
oplist.forEach((rec, i) => {
|
oplist.forEach((rec, i) => {
|
||||||
let title = '';
|
let title = '';
|
||||||
let clock = rec.type === '|';
|
let clock = rec.type === '|';
|
||||||
let label = clock ? `` : rec.type;
|
let label = clock ? `` : rec.mode ?? rec.type;
|
||||||
let clazz = notime ? ["draggable", "notime"] : ["draggable"];
|
let clazz = notime ? ["draggable", "notime"] : ["draggable"];
|
||||||
let notable = rec.note ? rec.note.split(' ').filter(v => v.charAt(0) === '#') : undefined;
|
let notable = rec.note ? rec.note.split(' ').filter(v => v.charAt(0) === '#') : undefined;
|
||||||
if (clock) { clazz.push('clock'); title = ` title="end of ops chain\ndrag/drop like an op\nops after this are disabled"` }
|
if (clock) { clazz.push('clock'); title = ` title="end of ops chain\ndrag/drop like an op\nops after this are disabled"` }
|
||||||
|
|
@ -512,6 +526,10 @@ export function opRender() {
|
||||||
|
|
||||||
export function init() {
|
export function init() {
|
||||||
|
|
||||||
|
if (api.devel.enabled) {
|
||||||
|
$('op:area').classList.remove('hide');
|
||||||
|
}
|
||||||
|
|
||||||
api.event.on('tool.mesh.face-normal', normal => {
|
api.event.on('tool.mesh.face-normal', normal => {
|
||||||
// console.log({ env.poppedRec });
|
// console.log({ env.poppedRec });
|
||||||
env.poppedRec.degrees = (Math.atan2(normal.y, normal.z) * RAD2DEG).round(2);
|
env.poppedRec.degrees = (Math.atan2(normal.y, normal.z) * RAD2DEG).round(2);
|
||||||
|
|
@ -606,6 +624,20 @@ export function init() {
|
||||||
updateStock();
|
updateStock();
|
||||||
opRender();
|
opRender();
|
||||||
api.uc.setVisible($('layer-animate'), env.isAnimate && env.isCamMode);
|
api.uc.setVisible($('layer-animate'), env.isAnimate && env.isCamMode);
|
||||||
|
|
||||||
|
if (!env.isCamMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove tab synth
|
||||||
|
api.widgets.filter((widget) => {
|
||||||
|
if (widget.track.synth) {
|
||||||
|
space.world.remove(widget.mesh);
|
||||||
|
Widget.Groups.remove(widget);
|
||||||
|
}
|
||||||
|
return !widget.track.synth
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
api.event.on("settings.saved", (settings) => {
|
api.event.on("settings.saved", (settings) => {
|
||||||
|
|
@ -745,6 +777,7 @@ export function init() {
|
||||||
case "trace": return opAddTrace();
|
case "trace": return opAddTrace();
|
||||||
case "pocket": return opAddPocket();
|
case "pocket": return opAddPocket();
|
||||||
case "helical": return opAddHelical();
|
case "helical": return opAddHelical();
|
||||||
|
case "area": return opAddArea();
|
||||||
case "flip":
|
case "flip":
|
||||||
// only one flip op permitted
|
// only one flip op permitted
|
||||||
for (let op of env.current.process.ops) {
|
for (let op of env.current.process.ops) {
|
||||||
|
|
@ -786,8 +819,27 @@ export function init() {
|
||||||
|
|
||||||
// COMMON TAB/TRACE EVENT HANDLERS
|
// COMMON TAB/TRACE EVENT HANDLERS
|
||||||
api.event.on("slice.begin", () => {
|
api.event.on("slice.begin", () => {
|
||||||
if (env.isCamMode) {
|
if (!env.isCamMode) {
|
||||||
clearPops();
|
return;
|
||||||
|
}
|
||||||
|
clearPops();
|
||||||
|
recreateTabs();
|
||||||
|
for (let group of Widget.Groups.list()) {
|
||||||
|
let root = group[0];
|
||||||
|
if (root.tabs)
|
||||||
|
for (let tab of Object.values(root.tabs)) {
|
||||||
|
let geo = tab.box.geometry.clone();
|
||||||
|
if (geo.index) geo = geo.toNonIndexed();
|
||||||
|
geo.translate(tab.x, tab.y, tab.z);
|
||||||
|
let bbg = BufferGeometryUtils.mergeGeometries([ geo ]);
|
||||||
|
let sw = newWidget(null, group);
|
||||||
|
let fwp = group[0].track.pos;
|
||||||
|
sw.loadGeometry(bbg);
|
||||||
|
sw._move(fwp.x, fwp.y, fwp.z);
|
||||||
|
api.widgets.add(sw);
|
||||||
|
sw.track.synth = true;
|
||||||
|
sw.track.indexed = root.track.indexed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,6 @@ function cylinderShow(onProgress,onDone){
|
||||||
cyls[face] = faces;
|
cyls[face] = faces;
|
||||||
CAM.cylinder_show(widget);
|
CAM.cylinder_show(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDone({faces:Object.keys(cyls).map(v => parseInt(v)),error});
|
onDone({faces:Object.keys(cyls).map(v => parseInt(v)),error});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
398
src/kiri/mode/cam/op-area.js
Normal file
398
src/kiri/mode/cam/op-area.js
Normal file
|
|
@ -0,0 +1,398 @@
|
||||||
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
|
import { CamOp } from './op.js';
|
||||||
|
import { Tool } from './tool.js';
|
||||||
|
import { newSlice } from '../../core/slice.js';
|
||||||
|
import { newPoint } from '../../../geo/point.js';
|
||||||
|
import { newPolygon } from '../../../geo/polygon.js';
|
||||||
|
import { polygons as POLY } from '../../../geo/polygons.js';
|
||||||
|
import { util as base_util } from '../../../geo/base.js';
|
||||||
|
import { CAM } from './driver-be.js';
|
||||||
|
|
||||||
|
const DEG2RAD = Math.PI / 180;
|
||||||
|
const clib = self.ClipperLib;
|
||||||
|
const ctyp = clib.ClipType;
|
||||||
|
const ptyp = clib.PolyType;
|
||||||
|
const cfil = clib.PolyFillType;
|
||||||
|
|
||||||
|
class OpArea extends CamOp {
|
||||||
|
constructor(state, op) {
|
||||||
|
super(state, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
async slice(progress) {
|
||||||
|
let { op, state } = this;
|
||||||
|
let { tool, mode, down, over, follow, expand, outline, refine, smooth } = op;
|
||||||
|
let { ov_topz, ov_botz, ov_conv } = op;
|
||||||
|
let { settings, widget, tabs, color } = state;
|
||||||
|
let { addSlices, setToolDiam, cutTabs, healPolys, shadowAt, workarea } = state;
|
||||||
|
|
||||||
|
let areaTool = new Tool(settings, tool);
|
||||||
|
let toolDiam = areaTool.fluteDiameter();
|
||||||
|
let toolOver = areaTool.hasTaper() ? over : toolDiam * over;
|
||||||
|
let zTop = ov_topz ? workarea.bottom_stock + ov_topz : workarea.top_stock;
|
||||||
|
let zBottom = ov_botz ? workarea.bottom_stock + ov_botz : workarea.bottom_part;
|
||||||
|
|
||||||
|
// also updates tab offsets
|
||||||
|
setToolDiam(toolDiam);
|
||||||
|
|
||||||
|
// selected area polygons: surfaces and edges
|
||||||
|
let { devel, edgeangle } = settings.controller;
|
||||||
|
let stack = [];
|
||||||
|
let surfaces = this.surfaces = [];
|
||||||
|
let areas = this.areas = [ stack ];
|
||||||
|
let polys = [];
|
||||||
|
|
||||||
|
function newArea() {
|
||||||
|
if (stack.length) {
|
||||||
|
stack = [];
|
||||||
|
areas.push(stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function newLayer() {
|
||||||
|
stack.push(newSlice());
|
||||||
|
return stack.peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
// gather area selections
|
||||||
|
for (let arr of (op.areas[widget.id] ?? [])) {
|
||||||
|
polys.push(newPolygon().fromArray(arr));
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect open poly edge segments into closed loops (when possible)
|
||||||
|
// surface and edge selections produce open polygons by default
|
||||||
|
polys = POLY.nest(healPolys(polys));
|
||||||
|
|
||||||
|
// gather surface selections
|
||||||
|
let vert = widget.getGeoVertices({ unroll: true, translate: true }).map(v => v.round(4));
|
||||||
|
let faces = CAM.surface_find(widget, (op.surfaces[widget.id] ?? []), (follow ?? edgeangle ?? 5) * DEG2RAD);
|
||||||
|
let fpoly = [];
|
||||||
|
let fminz = Infinity;
|
||||||
|
for (let face of faces) {
|
||||||
|
let i = face * 9;
|
||||||
|
fpoly.push(newPolygon()
|
||||||
|
.add(vert[i++], vert[i++], fminz = Math.min(fminz, vert[i++]))
|
||||||
|
.add(vert[i++], vert[i++], fminz = Math.min(fminz, vert[i++]))
|
||||||
|
.add(vert[i++], vert[i++], fminz = Math.min(fminz, vert[i++]))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// remove invalid edges (eg. when vertical walls are the only selection)
|
||||||
|
fpoly = fpoly.filter(p => p.area() > 0.001);
|
||||||
|
|
||||||
|
// add in unioned surface areas
|
||||||
|
polys.push(...POLY.setZ(POLY.union(fpoly, 0.00001, true), fminz));
|
||||||
|
|
||||||
|
// todo: implement `refine` and `smooth`
|
||||||
|
|
||||||
|
// expand selections (flattens z variable polys)
|
||||||
|
if (Math.abs(expand) > 0) {
|
||||||
|
let nupolys = polys.filter(p => p.open); // set aside open
|
||||||
|
for (let p of polys.filter(p => !p.open)) {
|
||||||
|
let expanded = POLY.expand([ p ], expand);
|
||||||
|
if (expanded) {
|
||||||
|
POLY.setZ(expanded, p.minZ());
|
||||||
|
nupolys.push(...expanded.flat());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
polys = nupolys;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process each area separately
|
||||||
|
let proc = 0;
|
||||||
|
let pinc = 1 / polys.length;
|
||||||
|
for (let area of polys) {
|
||||||
|
let bounds = area.getBounds3D();
|
||||||
|
|
||||||
|
if (devel) newLayer().output()
|
||||||
|
.setLayer("area", { line: 0xff8800 }, false)
|
||||||
|
.addPolys([ area ]);
|
||||||
|
|
||||||
|
newArea();
|
||||||
|
|
||||||
|
if (outline) {
|
||||||
|
// remove inner voids when processing outline only
|
||||||
|
area.inner = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode === 'clear') {
|
||||||
|
let zs = down ? base_util.lerp(zTop, zBottom, down) : [ bounds.min.z ];
|
||||||
|
let zroc = 0;
|
||||||
|
let zinc = 1 / zs.length;
|
||||||
|
let lzo;
|
||||||
|
outer: for (;;)
|
||||||
|
for (let z of zs) {
|
||||||
|
let slice = newLayer();
|
||||||
|
let layers = slice.output();
|
||||||
|
let outs = [];
|
||||||
|
let clip = [];
|
||||||
|
let shadow = shadowAt(z);
|
||||||
|
POLY.subtract([ area ], shadow, clip, undefined, undefined, 0);
|
||||||
|
POLY.offset(clip, [ -toolDiam / 2, -toolOver ], {
|
||||||
|
count: 999, outs, flat: true, z, minArea: 0
|
||||||
|
});
|
||||||
|
if (outs.length === 0) {
|
||||||
|
if (bounds && lzo > bounds.min.z) {
|
||||||
|
// try a bottom layer matching bottom of selection
|
||||||
|
zs = [ bounds.min.z ];
|
||||||
|
bounds = undefined;
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
// terminate z descent when no further output possible
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
|
// cut tabs when present
|
||||||
|
if (tabs) outs = cutTabs(tabs, outs);
|
||||||
|
slice.camLines = outs;
|
||||||
|
zroc += zinc;
|
||||||
|
lzo = z;
|
||||||
|
progress(proc + (pinc * zroc), 'clear');
|
||||||
|
if (devel) layers
|
||||||
|
.setLayer("shadow", { line: 0x0088ff }, false)
|
||||||
|
.addPolys(shadow);
|
||||||
|
layers
|
||||||
|
.setLayer("clear", { line: 0x88ff00 }, false)
|
||||||
|
.addPolys(outs);
|
||||||
|
// of the last output still cuts, we need an escape
|
||||||
|
if (z === zs.peek()) {
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
proc += pinc;
|
||||||
|
progress(proc, 'clear');
|
||||||
|
} else
|
||||||
|
if (mode === 'trace') {
|
||||||
|
let { tr_type } = op;
|
||||||
|
let zs = down ? base_util.lerp(zTop, bounds.min.z, down) : [ bounds.min.z ];
|
||||||
|
let zroc = 0;
|
||||||
|
let zinc = 1 / zs.length;
|
||||||
|
let lzo;
|
||||||
|
for (let z of zs) {
|
||||||
|
let slice = newLayer();
|
||||||
|
let layers = slice.output();
|
||||||
|
let outs = [];
|
||||||
|
if (tr_type === 'none') {
|
||||||
|
area = area.clone(true);
|
||||||
|
outs = [ zs.length > 1 ? area.setZ(z) : area ];
|
||||||
|
} else {
|
||||||
|
POLY.offset([ area ], tr_type === 'inside' ? [ -toolDiam / 2 ] : [ toolDiam / 2 ], {
|
||||||
|
count: 1, outs, flat: true, z, minArea: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (outs.length === 0) {
|
||||||
|
// terminate z descent when no further output possible
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// cut tabs when present
|
||||||
|
if (tabs) outs = cutTabs(tabs, outs);
|
||||||
|
slice.camLines = outs;
|
||||||
|
zroc += zinc;
|
||||||
|
lzo = z;
|
||||||
|
progress(proc + (pinc * zroc), 'trace');
|
||||||
|
layers
|
||||||
|
.setLayer("trace", { line: 0x88ff00 }, false)
|
||||||
|
.addPolys(outs);
|
||||||
|
}
|
||||||
|
proc += pinc;
|
||||||
|
progress(proc, 'trace');
|
||||||
|
} else
|
||||||
|
if (mode === 'surface') {
|
||||||
|
let { sr_type, sr_angle, tolerance } = op;
|
||||||
|
|
||||||
|
let resolution = tolerance || 0.05;
|
||||||
|
let raster = await self.get_raster_gpu({ mode: "tracing", resolution });
|
||||||
|
let surface = [];
|
||||||
|
let paths = [];
|
||||||
|
|
||||||
|
// prepare paths
|
||||||
|
if (sr_type === 'linear') {
|
||||||
|
// scan the area bounding box with rays at defined angle
|
||||||
|
let scan = scanBoxAtAngle(bounds, sr_angle * DEG2RAD, toolOver);
|
||||||
|
let lines = scan.map(line => {
|
||||||
|
let { a, b } = line;
|
||||||
|
return [ newPoint(a.x, a.y, 0).toClipper(), newPoint(b.x, b.y, 0).toClipper() ]
|
||||||
|
});
|
||||||
|
// use clipper to clip lines to the area polygon
|
||||||
|
let clip = new clib.Clipper();
|
||||||
|
let ctre = new clib.PolyTree();
|
||||||
|
clip.AddPaths(lines, ptyp.ptSubject, false);
|
||||||
|
clip.AddPaths(POLY.toClipper([ area ]), ptyp.ptClip, true);
|
||||||
|
if (clip.Execute(ctyp.ctIntersection, ctre, cfil.pftNonZero, cfil.pftEvenOdd)) {
|
||||||
|
for (let node of ctre.m_AllPolys) {
|
||||||
|
paths.push(POLY.fromClipperNode(node, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// convert resulting poly lines to raster float32 array groups
|
||||||
|
paths = paths.map(poly => poly.points.map(p => [ p.x, p.y ]).flat().toFloat32());
|
||||||
|
} else
|
||||||
|
if (sr_type === 'offset') {
|
||||||
|
// todo: progressive inset from perimeter
|
||||||
|
console.log({ sr_offset: toolOver });
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare tool mesh points
|
||||||
|
let toolBounds = new THREE.Box3()
|
||||||
|
.expandByPoint({ x: -toolDiam/2, y: -toolDiam/2, z: 0 })
|
||||||
|
.expandByPoint({ x: toolDiam/2, y: toolDiam/2, z: 0 });
|
||||||
|
let toolPos = areaTool.generateProfile(resolution).profile.slice();
|
||||||
|
for (let i=0; i<toolPos.length; i+= 3) {
|
||||||
|
toolBounds.expandByPoint({ x: toolPos[i], y: toolPos[i+1], z: toolPos[i+2] });
|
||||||
|
}
|
||||||
|
let toolData = { positions: toolPos, bounds: toolBounds };
|
||||||
|
|
||||||
|
// prepare terrain and raster paths over terrain
|
||||||
|
let vertices = widget.getGeoVertices({ unroll: true, translate: true });
|
||||||
|
let wbounds = bounds.clone().expandByVector({ x: toolDiam/2, y: toolDiam/2, z: 0 });
|
||||||
|
wbounds.min.z = zBottom;
|
||||||
|
wbounds.max.z = zTop;
|
||||||
|
await raster.loadTool({
|
||||||
|
sparseData: toolData
|
||||||
|
});
|
||||||
|
await raster.loadTerrain({
|
||||||
|
triangles: vertices,
|
||||||
|
boundsOverride: wbounds
|
||||||
|
});
|
||||||
|
let output = await raster.generateToolpaths({
|
||||||
|
paths,
|
||||||
|
step: toolOver / 2,
|
||||||
|
zFloor: zBottom - 1,
|
||||||
|
onProgress(pct) { console.log({ pct }); onupdate(pct/100, 100) }
|
||||||
|
});
|
||||||
|
raster.terminate();
|
||||||
|
|
||||||
|
// todo: port clever bits from topo3 for inside/outside detection and tab clipping
|
||||||
|
|
||||||
|
// convert terrain raster output back to open polylines
|
||||||
|
for (let path of output.paths) {
|
||||||
|
path = newPolygon().fromArray([1, ...path]);
|
||||||
|
surface.push(path);
|
||||||
|
newLayer().output()
|
||||||
|
.setLayer("linear", { line: 0x00ff00 }, false)
|
||||||
|
.addPolys([ path ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// output this surface
|
||||||
|
surfaces.push(surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addSlices(areas.flat());
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare(ops, progress) {
|
||||||
|
let { op, state, areas, surfaces } = this;
|
||||||
|
let { getPrintPoint, newLayer, pocket, polyEmit, setTool, setSpindle, tip2tipEmit } = ops;
|
||||||
|
let { process } = state.settings;
|
||||||
|
|
||||||
|
setTool(op.tool, op.rate);
|
||||||
|
setSpindle(op.spindle);
|
||||||
|
|
||||||
|
let printPoint = getPrintPoint();
|
||||||
|
|
||||||
|
// process surface paths
|
||||||
|
for (let surface of surfaces) {
|
||||||
|
let array = surface.map(poly => { return {
|
||||||
|
el: poly,
|
||||||
|
first: poly.first(),
|
||||||
|
last: poly.last()
|
||||||
|
} });
|
||||||
|
tip2tipEmit(array, printPoint, (next, first, count) => {
|
||||||
|
printPoint = polyEmit(next.el, 0, 1, printPoint, {});
|
||||||
|
newLayer();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip areas when processing surfaces
|
||||||
|
if (surfaces.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process areas as pockets
|
||||||
|
while (areas?.length) {
|
||||||
|
let min = {
|
||||||
|
dist: Infinity,
|
||||||
|
area: undefined
|
||||||
|
};
|
||||||
|
for (let area of areas.filter(p => !p.used)) {
|
||||||
|
// skip devel / debug only areas
|
||||||
|
let topPolys = area[0].camLines;
|
||||||
|
if (!topPolys) continue;
|
||||||
|
// select poly with largest area
|
||||||
|
let poly = topPolys.slice().sort((a,b) => b.area() - a.area())[0];
|
||||||
|
if (!poly) continue;
|
||||||
|
// compute move distance to top poly for efficient routing
|
||||||
|
let find = poly.findClosestPointTo(printPoint);
|
||||||
|
if (find.distance < min.dist) {
|
||||||
|
min.area = area;
|
||||||
|
min.dist = find.distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if we have a next-closest top poly, pocket that
|
||||||
|
if (min.area) {
|
||||||
|
min.area.used = true;
|
||||||
|
pocket({
|
||||||
|
cutdir: op.ov_conv,
|
||||||
|
depthFirst: process.camDepthFirst,
|
||||||
|
easeDown: op.down && process.easeDown ? op.down : 0,
|
||||||
|
progress: (n,m) => progress(n/m, "area"),
|
||||||
|
slices: min.area.filter(slice => slice.camLines)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// box2: THREE.Box2
|
||||||
|
// angle: radians (direction of each scan ray)
|
||||||
|
// step: spacing between parallel rays (world units)
|
||||||
|
function scanBoxAtAngle(box2, angle, step) {
|
||||||
|
const cx = (box2.min.x + box2.max.x) * 0.5;
|
||||||
|
const cy = (box2.min.y + box2.max.y) * 0.5;
|
||||||
|
const w = box2.max.x - box2.min.x;
|
||||||
|
const h = box2.max.y - box2.min.y;
|
||||||
|
|
||||||
|
// ray direction
|
||||||
|
const dx = Math.cos(angle);
|
||||||
|
const dy = Math.sin(angle);
|
||||||
|
|
||||||
|
// normal between rays (perpendicular to ray dir)
|
||||||
|
const nx = -dy;
|
||||||
|
const ny = dx;
|
||||||
|
|
||||||
|
// extent of the box along the normal
|
||||||
|
const extentN = Math.abs(nx) * w + Math.abs(ny) * h;
|
||||||
|
|
||||||
|
// length of each ray across the box (along ray dir)
|
||||||
|
const extentD = Math.abs(dx) * w + Math.abs(dy) * h;
|
||||||
|
|
||||||
|
// how many rays to cover the box; +1 so edges are covered
|
||||||
|
const count = Math.max(1, Math.ceil(extentN / step) + 1);
|
||||||
|
|
||||||
|
const halfSpan = step * (count - 1) * 0.5;
|
||||||
|
const halfD = extentD * 0.5;
|
||||||
|
const rays = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
// offset along normal
|
||||||
|
const o = -halfSpan + i * step;
|
||||||
|
const ox = cx + nx * o;
|
||||||
|
const oy = cy + ny * o;
|
||||||
|
|
||||||
|
// segment endpoints for this ray inside (or slightly outside) the box
|
||||||
|
const ax = ox - dx * halfD;
|
||||||
|
const ay = oy - dy * halfD;
|
||||||
|
const bx = ox + dx * halfD;
|
||||||
|
const by = oy + dy * halfD;
|
||||||
|
|
||||||
|
rays.push({
|
||||||
|
a: new THREE.Vector2(ax, ay),
|
||||||
|
b: new THREE.Vector2(bx, by),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return rays;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { OpArea };
|
||||||
|
|
@ -7,278 +7,277 @@ import { newPoint } from "../../../geo/point.js";
|
||||||
import { newSlice } from "../../core/slice.js";
|
import { newSlice } from "../../core/slice.js";
|
||||||
|
|
||||||
export class OpHelical extends CamOp {
|
export class OpHelical extends CamOp {
|
||||||
constructor(state, op) {
|
constructor(state, op) {
|
||||||
super(state, op);
|
super(state, op);
|
||||||
}
|
}
|
||||||
async slice(progress) {
|
|
||||||
let { op, state } = this;
|
|
||||||
let { settings, addSlices, widget, updateToolDiams, slicer } = state;
|
|
||||||
let { color } = state;
|
|
||||||
let {
|
|
||||||
cylinders,
|
|
||||||
forceStartAng,
|
|
||||||
startAng,
|
|
||||||
fromTop,
|
|
||||||
offOver,
|
|
||||||
offset,
|
|
||||||
down,
|
|
||||||
thru,
|
|
||||||
finish,
|
|
||||||
clockwise,
|
|
||||||
reverse,
|
|
||||||
entry,
|
|
||||||
entryOffset,
|
|
||||||
} = op;
|
|
||||||
let {stock} = settings
|
|
||||||
|
|
||||||
let tool = new Tool(settings, op.tool),
|
async slice(progress) {
|
||||||
toolDiam = tool.fluteDiameter(),
|
let { op, state } = this;
|
||||||
sliceOut = (this.sliceOut = []),
|
let { settings, addSlices, widget, updateToolDiams } = state;
|
||||||
startAngle = forceStartAng ? startAng : 0;
|
let {
|
||||||
|
cylinders,
|
||||||
updateToolDiams(toolDiam);
|
forceStartAng,
|
||||||
// console.log({cylinders})
|
startAng,
|
||||||
let faces = cylinders[widget.id] ?? [];
|
fromTop,
|
||||||
if (faces.faces) faces = faces.faces;
|
offOver,
|
||||||
let polys = [];
|
offset,
|
||||||
|
down,
|
||||||
//iterate over selected faces
|
thru,
|
||||||
for (let [i,face] of faces.entries()) {
|
finish,
|
||||||
//get poly info for the cylinder
|
|
||||||
let res
|
|
||||||
try{
|
|
||||||
res = cylinder_poly_find(
|
|
||||||
widget,
|
|
||||||
face
|
|
||||||
);
|
|
||||||
}catch(error){
|
|
||||||
// don't quit if a cylinder errors out, just skip
|
|
||||||
console.error(error)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
let { zmin, zmax, diam, center, interior, faces } = res;
|
|
||||||
// console.log({ zmin, zmax, diam, center, interior });
|
|
||||||
let radius = diam /2;
|
|
||||||
zmax = fromTop ? stock.z: zmax;
|
|
||||||
|
|
||||||
let radAdd,
|
|
||||||
zBottom = zmin - thru,
|
|
||||||
numSegs = faces.length / 2,
|
|
||||||
poly = newPolygon().setOpen();
|
|
||||||
|
|
||||||
if (offOver) {
|
|
||||||
//apply offset override
|
|
||||||
if (offset == "auto") {
|
|
||||||
radAdd = interior ? -offOver : offOver;
|
|
||||||
} else if (offset == "inside") {
|
|
||||||
radAdd = -offOver;
|
|
||||||
} else if (offset == "outside") {
|
|
||||||
radAdd = offOver;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//otherwise, calculate based on offset type
|
|
||||||
if (offset == "auto") {
|
|
||||||
radAdd = (interior ? -toolDiam : toolDiam) / 2;
|
|
||||||
} else if (offset == "inside") {
|
|
||||||
radAdd = -toolDiam / 2;
|
|
||||||
} else if (offset == "outside") {
|
|
||||||
radAdd = toolDiam / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
radius += radAdd;
|
|
||||||
|
|
||||||
if( radius <= 0 ){
|
|
||||||
//if negative radius, skip this cylinder
|
|
||||||
console.log('negative radius', radius);
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
let startPoint = center
|
|
||||||
.clone()
|
|
||||||
.setZ(zmax)
|
|
||||||
.add(
|
|
||||||
newPoint(
|
|
||||||
Math.cos(startAngle) * radius,
|
|
||||||
Math.sin(startAngle) * radius,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
let currentZ = zmax;
|
|
||||||
for (;;) {
|
|
||||||
let bottom = currentZ - down;
|
|
||||||
if ( bottom > zBottom ) {
|
|
||||||
//if not at the bottom, do a whole helix
|
|
||||||
let start = startPoint.setZ(currentZ),
|
|
||||||
end = startPoint.clone().setZ(bottom);
|
|
||||||
// console.log(currentZ, bottom, [start.z, end.z]);
|
|
||||||
let path = arcToPath(start, end, numSegs, {
|
|
||||||
clockwise,
|
clockwise,
|
||||||
radius,
|
reverse,
|
||||||
center,
|
entry,
|
||||||
});
|
entryOffset,
|
||||||
// console.log({ path, start, end, radius, center });
|
} = op;
|
||||||
poly.addPoints(path);
|
let { color } = state;
|
||||||
} else {
|
let { stock } = settings
|
||||||
//if at the bottom, do a partial helix
|
|
||||||
let toBottom = currentZ - zBottom,
|
|
||||||
ofFull = toBottom / down,
|
|
||||||
ofCircle = ofFull * (2 * Math.PI),
|
|
||||||
cwMultiplier = clockwise ? -1 : 1,
|
|
||||||
finalAngle = startAngle + (ofCircle*cwMultiplier),
|
|
||||||
finalEnd = center
|
|
||||||
.clone()
|
|
||||||
.setZ(zBottom)
|
|
||||||
.add(
|
|
||||||
newPoint(
|
|
||||||
Math.cos(finalAngle) * radius,
|
|
||||||
Math.sin(finalAngle) * radius,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
);
|
|
||||||
// console.log({down,toBottom,ofFull,ofCircle,startAngle,finalAngle,finalEnd});
|
|
||||||
|
|
||||||
//if not already very close to final point
|
let tool = new Tool(settings, op.tool),
|
||||||
if( ofCircle >= 0.001 ){
|
toolDiam = tool.fluteDiameter(),
|
||||||
//circle down to final point
|
sliceOut = (this.sliceOut = []),
|
||||||
poly.addPoints(
|
startAngle = forceStartAng ? startAng : 0;
|
||||||
arcToPath(startPoint.setZ(currentZ), finalEnd, numSegs , {
|
|
||||||
clockwise,
|
|
||||||
radius,
|
|
||||||
center,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if starting at the bottom, reverse poly
|
updateToolDiams(toolDiam);
|
||||||
if ( reverse ){
|
// console.log({cylinders});
|
||||||
poly.reverse();
|
let faces = cylinders[widget.id] ?? [];
|
||||||
}
|
if (faces.faces) faces = faces.faces;
|
||||||
|
let polys = [];
|
||||||
|
|
||||||
if ( entry ){
|
//iterate over selected faces
|
||||||
//get first z of poly to use for entry
|
for (let [i, face] of faces.entries()) {
|
||||||
let firstZ = poly.first().z;
|
//get poly info for the cylinder
|
||||||
//create new pointArray
|
let res
|
||||||
let entry =[newPoint(0,0,0)];
|
try {
|
||||||
//add center point
|
res = cylinder_poly_find(
|
||||||
let entryCenter = center.clone().setZ(firstZ)
|
widget,
|
||||||
|
face
|
||||||
//if doing a curved enter, add more
|
);
|
||||||
if ( entryOffset > 0 ){
|
} catch (error) {
|
||||||
if ( entryOffset > radius ){
|
// don't quit if a cylinder errors out, just skip
|
||||||
console.error("entryOffset must be less than radius of helix");
|
console.error(error)
|
||||||
}else{
|
continue
|
||||||
//calculate entry center
|
|
||||||
let lineOut = radius - entryOffset;
|
|
||||||
let centerOffset = (entryOffset**2 + 2*entryOffset*lineOut) / (2*(entryOffset + lineOut));
|
|
||||||
//add entry points
|
|
||||||
entry.push(
|
|
||||||
newPoint(0,-lineOut,0),
|
|
||||||
...arcToPath(
|
|
||||||
newPoint(0,-lineOut,0),
|
|
||||||
newPoint(radius,0,0),
|
|
||||||
128,
|
|
||||||
{
|
|
||||||
clockwise:false,
|
|
||||||
radius:lineOut,
|
|
||||||
center:newPoint(centerOffset,0,0)
|
|
||||||
}
|
|
||||||
),
|
|
||||||
newPoint(radius,0,0),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//for each point
|
let { zmin, zmax, diam, center, interior, faces } = res;
|
||||||
//rotate by start angle
|
// console.log({ zmin, zmax, diam, center, interior });
|
||||||
// add to hole center
|
let radius = diam / 2;
|
||||||
let invert = ((clockwise && !reverse ) || (!clockwise && reverse) ) ? -1 : 1
|
zmax = fromTop ? stock.z : zmax;
|
||||||
let entryAngle = reverse ? finalAngle : startAngle
|
|
||||||
entry = entry.map(p => {
|
|
||||||
// TODO: there's totally a way to do this with a matrix
|
|
||||||
// logical XOR
|
|
||||||
p.y *= invert
|
|
||||||
p.rotate(entryAngle)
|
|
||||||
return p.add(entryCenter)
|
|
||||||
})
|
|
||||||
//append to start of poly
|
|
||||||
poly = newPolygon().setOpen().addPoints(entry).addPoints(poly.points);
|
|
||||||
}
|
|
||||||
//if doing a finish pass, do a full circle at the bottom
|
|
||||||
if ( finish && !reverse ){
|
|
||||||
poly.addPoints(
|
|
||||||
arcToPath(finalEnd, finalEnd, numSegs, {
|
|
||||||
clockwise,
|
|
||||||
radius,
|
|
||||||
center,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
poly.append(
|
|
||||||
finalEnd.clone().setZ(zBottom),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
currentZ = bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
progress(i/faces.length, "Helical intrerpolation");
|
let radAdd,
|
||||||
polys.push(poly);
|
zBottom = zmin - thru,
|
||||||
|
numSegs = faces.length / 2,
|
||||||
|
poly = newPolygon().setOpen();
|
||||||
|
|
||||||
|
if (offOver) {
|
||||||
|
//apply offset override
|
||||||
|
if (offset == "auto") {
|
||||||
|
radAdd = interior ? -offOver : offOver;
|
||||||
|
} else if (offset == "inside") {
|
||||||
|
radAdd = -offOver;
|
||||||
|
} else if (offset == "outside") {
|
||||||
|
radAdd = offOver;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//otherwise, calculate based on offset type
|
||||||
|
if (offset == "auto") {
|
||||||
|
radAdd = (interior ? -toolDiam : toolDiam) / 2;
|
||||||
|
} else if (offset == "inside") {
|
||||||
|
radAdd = -toolDiam / 2;
|
||||||
|
} else if (offset == "outside") {
|
||||||
|
radAdd = toolDiam / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
radius += radAdd;
|
||||||
|
|
||||||
|
if (radius <= 0) {
|
||||||
|
//if negative radius, skip this cylinder
|
||||||
|
console.log('negative radius', radius);
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
let startPoint = center
|
||||||
|
.clone()
|
||||||
|
.setZ(zmax)
|
||||||
|
.add(
|
||||||
|
newPoint(
|
||||||
|
Math.cos(startAngle) * radius,
|
||||||
|
Math.sin(startAngle) * radius,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
let currentZ = zmax;
|
||||||
|
for (; ;) {
|
||||||
|
let bottom = currentZ - down;
|
||||||
|
if (bottom > zBottom) {
|
||||||
|
//if not at the bottom, do a whole helix
|
||||||
|
let start = startPoint.setZ(currentZ),
|
||||||
|
end = startPoint.clone().setZ(bottom);
|
||||||
|
// console.log(currentZ, bottom, [start.z, end.z]);
|
||||||
|
let path = arcToPath(start, end, numSegs, {
|
||||||
|
clockwise,
|
||||||
|
radius,
|
||||||
|
center,
|
||||||
|
});
|
||||||
|
// console.log({ path, start, end, radius, center });
|
||||||
|
poly.addPoints(path);
|
||||||
|
} else {
|
||||||
|
//if at the bottom, do a partial helix
|
||||||
|
let toBottom = currentZ - zBottom,
|
||||||
|
ofFull = toBottom / down,
|
||||||
|
ofCircle = ofFull * (2 * Math.PI),
|
||||||
|
cwMultiplier = clockwise ? -1 : 1,
|
||||||
|
finalAngle = startAngle + (ofCircle * cwMultiplier),
|
||||||
|
finalEnd = center
|
||||||
|
.clone()
|
||||||
|
.setZ(zBottom)
|
||||||
|
.add(
|
||||||
|
newPoint(
|
||||||
|
Math.cos(finalAngle) * radius,
|
||||||
|
Math.sin(finalAngle) * radius,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// console.log({down,toBottom,ofFull,ofCircle,startAngle,finalAngle,finalEnd});
|
||||||
|
//if not already very close to final point
|
||||||
|
if (ofCircle >= 0.001) {
|
||||||
|
//circle down to final point
|
||||||
|
poly.addPoints(
|
||||||
|
arcToPath(startPoint.setZ(currentZ), finalEnd, numSegs, {
|
||||||
|
clockwise,
|
||||||
|
radius,
|
||||||
|
center,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if starting at the bottom, reverse poly
|
||||||
|
if (reverse) {
|
||||||
|
poly.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry) {
|
||||||
|
//get first z of poly to use for entry
|
||||||
|
let firstZ = poly.first().z;
|
||||||
|
//create new pointArray
|
||||||
|
let entry = [newPoint(0, 0, 0)];
|
||||||
|
//add center point
|
||||||
|
let entryCenter = center.clone().setZ(firstZ)
|
||||||
|
|
||||||
|
//if doing a curved enter, add more
|
||||||
|
if (entryOffset > 0) {
|
||||||
|
if (entryOffset > radius) {
|
||||||
|
console.error("entryOffset must be less than radius of helix");
|
||||||
|
} else {
|
||||||
|
//calculate entry center
|
||||||
|
let lineOut = radius - entryOffset;
|
||||||
|
let centerOffset = (entryOffset ** 2 + 2 * entryOffset * lineOut) / (2 * (entryOffset + lineOut));
|
||||||
|
//add entry points
|
||||||
|
entry.push(
|
||||||
|
newPoint(0, -lineOut, 0),
|
||||||
|
...arcToPath(
|
||||||
|
newPoint(0, -lineOut, 0),
|
||||||
|
newPoint(radius, 0, 0),
|
||||||
|
128,
|
||||||
|
{
|
||||||
|
clockwise: false,
|
||||||
|
radius: lineOut,
|
||||||
|
center: newPoint(centerOffset, 0, 0)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
newPoint(radius, 0, 0),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//for each point
|
||||||
|
//rotate by start angle
|
||||||
|
// add to hole center
|
||||||
|
let invert = ((clockwise && !reverse) || (!clockwise && reverse)) ? -1 : 1
|
||||||
|
let entryAngle = reverse ? finalAngle : startAngle
|
||||||
|
entry = entry.map(p => {
|
||||||
|
// TODO: there's totally a way to do this with a matrix
|
||||||
|
// logical XOR
|
||||||
|
p.y *= invert
|
||||||
|
p.rotate(entryAngle)
|
||||||
|
return p.add(entryCenter)
|
||||||
|
})
|
||||||
|
//append to start of poly
|
||||||
|
poly = newPolygon().setOpen().addPoints(entry).addPoints(poly.points);
|
||||||
|
}
|
||||||
|
//if doing a finish pass, do a full circle at the bottom
|
||||||
|
if (finish && !reverse) {
|
||||||
|
poly.addPoints(
|
||||||
|
arcToPath(finalEnd, finalEnd, numSegs, {
|
||||||
|
clockwise,
|
||||||
|
radius,
|
||||||
|
center,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
poly.append(
|
||||||
|
finalEnd.clone().setZ(zBottom),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
currentZ = bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress(i / faces.length, "Helical intrerpolation");
|
||||||
|
polys.push(poly);
|
||||||
|
}
|
||||||
|
|
||||||
|
let slice = newSlice(0);
|
||||||
|
slice.camTrace = { tool: op.tool, rate: op.feed, plunge: op.rate };
|
||||||
|
slice.camLines = polys;
|
||||||
|
|
||||||
|
slice
|
||||||
|
.output()
|
||||||
|
.setLayer("Helical", { face: color, line: color })
|
||||||
|
.addPolys(slice.camLines);
|
||||||
|
|
||||||
|
addSlices(slice);
|
||||||
|
sliceOut.push(slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
let slice = newSlice(0);
|
async prepare(ops, progress) {
|
||||||
|
let {
|
||||||
|
setTool,
|
||||||
|
setSpindle,
|
||||||
|
polyEmit,
|
||||||
|
setPrintPoint,
|
||||||
|
getPrintPoint,
|
||||||
|
} = ops;
|
||||||
|
let { tool, spindle, rate, feed } = this.op;
|
||||||
|
|
||||||
slice.camTrace = { tool: op.tool, rate: op.feed, plunge: op.rate };
|
setTool(tool, feed, rate);
|
||||||
slice.camLines = polys;
|
setSpindle(spindle);
|
||||||
|
|
||||||
slice
|
let [polys] = this.sliceOut.map((s) => s.camLines);
|
||||||
.output()
|
let pp = getPrintPoint();
|
||||||
.setLayer("Helical", { face: color, line: color })
|
polys = polys.slice();
|
||||||
.addPolys(slice.camLines);
|
|
||||||
addSlices(slice);
|
|
||||||
sliceOut.push(slice);
|
|
||||||
}
|
|
||||||
|
|
||||||
async prepare(ops, progress) {
|
for (;;) {
|
||||||
let { op, state } = this;
|
let closestDist = Infinity,
|
||||||
let { settings, widget, addSlices, updateToolDiams } = state;
|
closestI,
|
||||||
let {
|
closest = null,
|
||||||
setTool,
|
dist,
|
||||||
setSpindle,
|
poly;
|
||||||
polyEmit,
|
|
||||||
camOut,
|
|
||||||
setPrintPoint,
|
|
||||||
getPrintPoint,
|
|
||||||
} = ops;
|
|
||||||
let { tool, spindle, rate, feed } = op;
|
|
||||||
setTool(tool, feed, rate);
|
|
||||||
setSpindle(spindle);
|
|
||||||
|
|
||||||
let [polys] = this.sliceOut.map((s) => s.camLines);
|
for (let i = 0; i < polys.length; i++) {
|
||||||
let pp = getPrintPoint();
|
if (!polys[i]) continue;
|
||||||
|
if ((dist = polys[i].first().distTo2D(pp)) < closestDist) {
|
||||||
|
closestDist = dist;
|
||||||
|
closest = polys[i];
|
||||||
|
closestI = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
polys = polys.slice();
|
if (!closest) break;
|
||||||
for (;;) {
|
poly = polys[closestI]
|
||||||
let closestDist = Infinity,
|
polys[closestI] = null;
|
||||||
closestI,
|
pp = polyEmit(poly, 0, 1, poly.points[0])
|
||||||
closest = null,
|
|
||||||
dist,
|
|
||||||
poly;
|
|
||||||
|
|
||||||
for (let i = 0; i < polys.length; i++) {
|
|
||||||
if (!polys[i]) continue;
|
|
||||||
if ((dist = polys[i].first().distTo2D(pp)) < closestDist) {
|
|
||||||
closestDist = dist;
|
|
||||||
closest = polys[i];
|
|
||||||
closestI = i;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!closest) break;
|
setPrintPoint(pp);
|
||||||
poly = polys[closestI]
|
|
||||||
polys[closestI] = null;
|
|
||||||
//emit
|
|
||||||
pp = polyEmit(poly,0,1,poly.points[0])
|
|
||||||
}
|
}
|
||||||
setPrintPoint(pp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ export class OpIndex extends CamOp {
|
||||||
throw 'index op requires indexed stock';
|
throw 'index op requires indexed stock';
|
||||||
}
|
}
|
||||||
let { widget, updateSlicer, computeShadows, setAxisIndex } = state;
|
let { widget, updateSlicer, computeShadows, setAxisIndex } = state;
|
||||||
this.degrees = setAxisIndex(op.degrees, op.absolute);
|
this.degrees = await setAxisIndex(op.degrees, op.absolute);
|
||||||
// force recompute of topo
|
// force recompute of topo
|
||||||
widget.topo = undefined;
|
widget.topo = undefined;
|
||||||
updateSlicer();
|
updateSlicer();
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,41 @@
|
||||||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
import { OpXRay } from './op-xray.js';
|
|
||||||
import { OpShadow } from './op-shadow.js';
|
|
||||||
import { OpLevel } from './op-level.js';
|
|
||||||
import { OpRough } from './op-rough.js';
|
|
||||||
import { OpOutline } from './op-outline.js';
|
|
||||||
import { OpContour } from './op-contour.js';
|
|
||||||
import { OpPocket } from './op-pocket.js';
|
|
||||||
import { OpLathe } from './op-lathe.js';
|
|
||||||
import { OpTrace } from './op-trace.js';
|
|
||||||
import { OpDrill } from './op-drill.js';
|
|
||||||
import { OpRegister } from './op-register.js';
|
|
||||||
import { OpLaserOn } from './op-laser-on.js';
|
|
||||||
import { OpLaserOff } from './op-laser-off.js';
|
|
||||||
import { OpGCode } from './op-gcode.js';
|
|
||||||
import { OpIndex } from './op-index.js';
|
|
||||||
import { CamOp } from './op.js';
|
import { CamOp } from './op.js';
|
||||||
|
import { OpArea } from './op-area.js';
|
||||||
|
import { OpContour } from './op-contour.js';
|
||||||
|
import { OpDrill } from './op-drill.js';
|
||||||
|
import { OpGCode } from './op-gcode.js';
|
||||||
import { OpHelical } from './op-helical.js';
|
import { OpHelical } from './op-helical.js';
|
||||||
|
import { OpIndex } from './op-index.js';
|
||||||
|
import { OpLaserOff } from './op-laser-off.js';
|
||||||
|
import { OpLaserOn } from './op-laser-on.js';
|
||||||
|
import { OpLathe } from './op-lathe.js';
|
||||||
|
import { OpLevel } from './op-level.js';
|
||||||
|
import { OpOutline } from './op-outline.js';
|
||||||
|
import { OpPocket } from './op-pocket.js';
|
||||||
|
import { OpRegister } from './op-register.js';
|
||||||
|
import { OpRough } from './op-rough.js';
|
||||||
|
import { OpShadow } from './op-shadow.js';
|
||||||
|
import { OpTrace } from './op-trace.js';
|
||||||
|
import { OpXRay } from './op-xray.js';
|
||||||
|
|
||||||
export const ops = {
|
export const ops = {
|
||||||
"xray": OpXRay,
|
"area": OpArea,
|
||||||
"shadow": OpShadow,
|
|
||||||
"level": OpLevel,
|
|
||||||
"rough": OpRough,
|
|
||||||
"outline": OpOutline,
|
|
||||||
"contour": OpContour,
|
"contour": OpContour,
|
||||||
"pocket": OpPocket,
|
|
||||||
"lathe": OpLathe,
|
|
||||||
"trace": OpTrace,
|
|
||||||
"drill": OpDrill,
|
"drill": OpDrill,
|
||||||
"register": OpRegister,
|
"flip": CamOp,
|
||||||
"helical": OpHelical,
|
|
||||||
"laser on": OpLaserOn,
|
|
||||||
"laser off": OpLaserOff,
|
|
||||||
"gcode": OpGCode,
|
"gcode": OpGCode,
|
||||||
|
"helical": OpHelical,
|
||||||
"index": OpIndex,
|
"index": OpIndex,
|
||||||
"flip": CamOp
|
"laser off": OpLaserOff,
|
||||||
|
"laser on": OpLaserOn,
|
||||||
|
"lathe": OpLathe,
|
||||||
|
"level": OpLevel,
|
||||||
|
"outline": OpOutline,
|
||||||
|
"pocket": OpPocket,
|
||||||
|
"register": OpRegister,
|
||||||
|
"rough": OpRough,
|
||||||
|
"shadow": OpShadow,
|
||||||
|
"trace": OpTrace,
|
||||||
|
"xray": OpXRay
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ export async function cam_prepare(widall, settings, update) {
|
||||||
print.output = [];
|
print.output = [];
|
||||||
|
|
||||||
let point;
|
let point;
|
||||||
widgets.forEach((widget, index) => {
|
widgets.filter(w => !w.isSynth()).forEach((widget, index) => {
|
||||||
point = prepEach(widget, settings, print, point, (progress, msg) => {
|
point = prepEach(widget, settings, print, point, (progress, msg) => {
|
||||||
update((index * weight + progress * weight) * 0.75, msg || "prepare");
|
update((index * weight + progress * weight) * 0.75, msg || "prepare");
|
||||||
});
|
});
|
||||||
|
|
@ -337,7 +337,7 @@ export function prepEach(widget, settings, print, firstPoint, update) {
|
||||||
// 1. move to safe z of current point preserving angle
|
// 1. move to safe z of current point preserving angle
|
||||||
// 2. move to safe z of new point preserving old angle
|
// 2. move to safe z of new point preserving old angle
|
||||||
// 3. move to safe z of new point with new angle
|
// 3. move to safe z of new point with new angle
|
||||||
if (lop && lop !== currentOp && lastPoint) {
|
if (lop !== currentOp && lastPoint) {
|
||||||
// compensate for applyWidgetMovement() applied to lastPoint
|
// compensate for applyWidgetMovement() applied to lastPoint
|
||||||
let lpo = lastPoint.clone().move({ x: -wmx, y: -wmy, z: -zadd });
|
let lpo = lastPoint.clone().move({ x: -wmx, y: -wmy, z: -zadd });
|
||||||
camOut(lpo.clone().setZ(zsafe).setA(lastPoint.a), 0);
|
camOut(lpo.clone().setZ(zsafe).setA(lastPoint.a), 0);
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,10 @@ import { CAM } from './driver-be.js';
|
||||||
* @param {Function} output
|
* @param {Function} output
|
||||||
*/
|
*/
|
||||||
export async function cam_slice(settings, widget, onupdate, ondone) {
|
export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
|
if (widget.track.synth) return ondone();
|
||||||
|
|
||||||
|
let tabW = widget.group.filter(w => w != widget);
|
||||||
|
|
||||||
let proc = settings.process,
|
let proc = settings.process,
|
||||||
sliceAll = widget.slices = [],
|
sliceAll = widget.slices = [],
|
||||||
camOps = widget.camops = [],
|
camOps = widget.camops = [],
|
||||||
|
|
@ -87,7 +91,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
bottom_z, bottom_cut
|
bottom_z, bottom_cut
|
||||||
}, 3);
|
}, 3);
|
||||||
|
|
||||||
// console.log({ track, bounds, stock, workarea });
|
// console.log({ bounds, stock, track, workarea });
|
||||||
|
|
||||||
return structuredClone(workarea);
|
return structuredClone(workarea);
|
||||||
};
|
};
|
||||||
|
|
@ -95,26 +99,6 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
// initial setup
|
// initial setup
|
||||||
var_compute();
|
var_compute();
|
||||||
|
|
||||||
if (tabs) {
|
|
||||||
// make tab polygons
|
|
||||||
tabs.forEach(tab => {
|
|
||||||
let zero = newPoint(0, 0, 0),
|
|
||||||
point = newPoint(tab.pos.x, tab.pos.y, tab.pos.z),
|
|
||||||
poly = newPolygon().centerRectangle(zero, tab.dim.x, tab.dim.y),
|
|
||||||
[rx, ry, rz, rw] = tab.rot,
|
|
||||||
m4 = new THREE.Matrix4().makeRotationFromQuaternion(
|
|
||||||
new THREE.Quaternion(rx, ry, rz, rw)
|
|
||||||
);
|
|
||||||
poly.points = poly.points
|
|
||||||
.map(p => new THREE.Vector3(p.x, p.y, p.z).applyMatrix4(m4))
|
|
||||||
.map(v => newPoint(v.x, v.y, v.z));
|
|
||||||
poly.move(point);
|
|
||||||
tab.poly = poly;
|
|
||||||
// tslice.output().setLayer("tabs", 0xff0000).addPoly(poly);
|
|
||||||
// sliceAll.push(tslice);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function error(msg) {
|
function error(msg) {
|
||||||
ondone(msg);
|
ondone(msg);
|
||||||
}
|
}
|
||||||
|
|
@ -155,7 +139,6 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
alert(`invalid z bottom ${(zMin / units).round(3)} >= bounds z max ${(zMax / units).round(3)}`);
|
alert(`invalid z bottom ${(zMin / units).round(3)} >= bounds z max ${(zMax / units).round(3)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mark = Date.now();
|
|
||||||
let opList = [];
|
let opList = [];
|
||||||
let opSum = 0;
|
let opSum = 0;
|
||||||
let opTot = 0;
|
let opTot = 0;
|
||||||
|
|
@ -174,6 +157,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
isIndexed,
|
isIndexed,
|
||||||
ops: opList,
|
ops: opList,
|
||||||
setAxisIndex,
|
setAxisIndex,
|
||||||
|
setToolDiam,
|
||||||
settings,
|
settings,
|
||||||
shadowAt,
|
shadowAt,
|
||||||
slicer,
|
slicer,
|
||||||
|
|
@ -190,6 +174,30 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
};
|
};
|
||||||
let tracker = setSliceTracker({ rotation: 0 });
|
let tracker = setSliceTracker({ rotation: 0 });
|
||||||
|
|
||||||
|
async function updateTab(tab) {
|
||||||
|
tab.setAxisIndex(isIndexed ? -axisIndex : 0)
|
||||||
|
let ts = new cam_slicer(tab);
|
||||||
|
let si = Object.keys(ts.zList).map(k => parseFloat(k));
|
||||||
|
si = [ ...si.map(v => v-0.01), ...si.map(v => v+0.01) ];
|
||||||
|
let zt = Math.max(...si);
|
||||||
|
let zb = Math.min(...si);
|
||||||
|
let shadow;
|
||||||
|
await ts.slice(si, { each: data => {
|
||||||
|
if (shadow) {
|
||||||
|
shadow = POLY.union([...shadow, ...data.polys]);
|
||||||
|
} else {
|
||||||
|
shadow = data.polys;
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
return {
|
||||||
|
top: zt,
|
||||||
|
poly: shadow[0],
|
||||||
|
pos: { z: (zt+zb)/2 },
|
||||||
|
dim: { z: (zt-zb) },
|
||||||
|
NEW: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateSlicer() {
|
function updateSlicer() {
|
||||||
slicer = state.slicer = new cam_slicer(widget);
|
slicer = state.slicer = new cam_slicer(widget);
|
||||||
}
|
}
|
||||||
|
|
@ -201,6 +209,15 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setToolDiam(toolDiam) {
|
||||||
|
updateToolDiams(toolDiam);
|
||||||
|
if (tabs) {
|
||||||
|
tabs.forEach(tab => {
|
||||||
|
tab.off = POLY.expand([ tab.poly ], toolDiam / 2).flat();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateToolDiams(toolDiam) {
|
function updateToolDiams(toolDiam) {
|
||||||
minToolDiam = Math.min(minToolDiam, toolDiam);
|
minToolDiam = Math.min(minToolDiam, toolDiam);
|
||||||
maxToolDiam = Math.max(maxToolDiam, toolDiam);
|
maxToolDiam = Math.max(maxToolDiam, toolDiam);
|
||||||
|
|
@ -212,30 +229,23 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
// find closest shadow above and use to speed up delta shadow gen
|
// find closest shadow above and use to speed up delta shadow gen
|
||||||
let minZabove;
|
|
||||||
let zover = Object.keys(shadows).map(v => parseFloat(v)).filter(v => v > z);
|
let zover = Object.keys(shadows).map(v => parseFloat(v)).filter(v => v > z);
|
||||||
for (let zkey of zover) {
|
let minZabove = Math.min(Infinity, ...zover);
|
||||||
if (minZabove && zkey < minZabove) {
|
|
||||||
minZabove = zkey;
|
|
||||||
} else {
|
|
||||||
minZabove = zkey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let shadow = computeShadowAt(widget, z, minZabove);
|
let shadow = computeShadowAt(widget, z, minZabove);
|
||||||
if (minZabove) {
|
if (minZabove < Infinity) {
|
||||||
// const merge = shadow.length;
|
|
||||||
// const plus = shadows[minZabove].length;
|
|
||||||
// const mark = Date.now();
|
|
||||||
shadow = POLY.union([...shadow, ...shadows[minZabove]], 0.001, true);
|
shadow = POLY.union([...shadow, ...shadows[minZabove]], 0.001, true);
|
||||||
// console.log({merge, plus, equals: shadow.length, time: Date.now() - mark});
|
|
||||||
}
|
}
|
||||||
return shadows[z] = POLY.setZ(shadow, z);
|
return shadows[z] = POLY.setZ(shadow, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setAxisIndex(degrees = 0, absolute = true) {
|
async function setAxisIndex(degrees = 0, absolute = true) {
|
||||||
axisIndex = absolute ? degrees : (axisIndex || 0) + degrees;
|
axisIndex = absolute ? degrees : (axisIndex || 0) + degrees;
|
||||||
axisRotation = (Math.PI / 180) * axisIndex;
|
axisRotation = (Math.PI / 180) * axisIndex;
|
||||||
widget.setAxisIndex(isIndexed ? -axisIndex : 0);
|
widget.setAxisIndex(isIndexed ? -axisIndex : 0);
|
||||||
|
state.tabs = tabs = [];
|
||||||
|
for (let tab of tabW) {
|
||||||
|
tabs.push(await updateTab(tab));
|
||||||
|
}
|
||||||
return isIndexed ? -axisIndex : 0;
|
return isIndexed ? -axisIndex : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -300,7 +310,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// call slice() function on all ops in order
|
// call slice() function on all ops in order
|
||||||
setAxisIndex();
|
await setAxisIndex();
|
||||||
updateSlicer();
|
updateSlicer();
|
||||||
for (let op of opList) {
|
for (let op of opList) {
|
||||||
let weight = op.weight();
|
let weight = op.weight();
|
||||||
|
|
@ -326,12 +336,6 @@ export async function cam_slice(settings, widget, onupdate, ondone) {
|
||||||
zTop,
|
zTop,
|
||||||
workarea: workover
|
workarea: workover
|
||||||
});
|
});
|
||||||
// console.log({
|
|
||||||
// op,
|
|
||||||
// workover,
|
|
||||||
// bounds: structuredClone(bounds),
|
|
||||||
// stock: structuredClone(stock)
|
|
||||||
// });
|
|
||||||
await op.slice((progress, message) => {
|
await op.slice((progress, message) => {
|
||||||
onupdate((opSum + (progress * weight)) / opTot, message || op.type());
|
onupdate((opSum + (progress * weight)) / opTot, message || op.type());
|
||||||
});
|
});
|
||||||
|
|
@ -595,7 +599,7 @@ export function cylinder_poly_find(widget, face) {
|
||||||
let zmid = (zmin + zmax) / 2;
|
let zmid = (zmin + zmax) / 2;
|
||||||
let cylVerts = new Float32Array(faces.length * 9);
|
let cylVerts = new Float32Array(faces.length * 9);
|
||||||
let opts = {
|
let opts = {
|
||||||
dedup: false,
|
dedup: true,
|
||||||
edges: false,
|
edges: false,
|
||||||
over: true
|
over: true
|
||||||
};
|
};
|
||||||
|
|
@ -648,7 +652,7 @@ export function cylinder_poly_find(widget, face) {
|
||||||
*/
|
*/
|
||||||
export async function holes(settings, widget, individual, rec, onProgress) {
|
export async function holes(settings, widget, individual, rec, onProgress) {
|
||||||
|
|
||||||
let { tool, mark, precision } = rec //TODO: display some visual difference if mark is selected
|
let { tool, precision } = rec //TODO: display some visual difference if mark is selected
|
||||||
let toolDiam = new Tool(settings, tool).fluteDiameter()
|
let toolDiam = new Tool(settings, tool).fluteDiameter()
|
||||||
let diam = individual ? 1 : toolDiam; // sets default diameter when select individual used
|
let diam = individual ? 1 : toolDiam; // sets default diameter when select individual used
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@ export class Topo {
|
||||||
if (poly.length > 1) {
|
if (poly.length > 1) {
|
||||||
lines.push(poly);
|
lines.push(poly);
|
||||||
}
|
}
|
||||||
// raize output points when inside tab boundaries
|
// raise output points when inside tab boundaries
|
||||||
if (!inside && tabsOn && clipTab.length)
|
if (!inside && tabsOn && clipTab.length)
|
||||||
for (let poly of lines) {
|
for (let poly of lines) {
|
||||||
for (let p of poly.points) {
|
for (let p of poly.points) {
|
||||||
|
|
|
||||||
|
|
@ -2024,6 +2024,18 @@ details[open] summary::after {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
/* background-color: #f8f8f8; */
|
/* background-color: #f8f8f8; */
|
||||||
}
|
}
|
||||||
|
#device-action {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
#device-action a {
|
||||||
|
right: 0;
|
||||||
|
position: absolute;
|
||||||
|
border-bottom: 1px dotted;
|
||||||
|
}
|
||||||
|
#device-action a:hover {
|
||||||
|
color: #888;
|
||||||
|
border-bottom: 1px transparent;
|
||||||
|
}
|
||||||
#device-action button, #tool-action button {
|
#device-action button, #tool-action button {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
|
||||||
|
|
@ -461,6 +461,7 @@
|
||||||
<div title="2.5D tracing along X or Y axis used for complex part features">contour</div>
|
<div title="2.5D tracing along X or Y axis used for complex part features">contour</div>
|
||||||
<div title="clear areas above selected surfaces">pocket</div>
|
<div title="clear areas above selected surfaces">pocket</div>
|
||||||
<div title="follow a helix around circular paths">helical</div>
|
<div title="follow a helix around circular paths">helical</div>
|
||||||
|
<div title="perform configurable operations on selected areas" id="op:area" class="hide">area</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -545,6 +546,7 @@
|
||||||
<div class="grow"></div>
|
<div class="grow"></div>
|
||||||
<button id="device-save" lk="save">save</button>
|
<button id="device-save" lk="save">save</button>
|
||||||
<div class="grow"></div>
|
<div class="grow"></div>
|
||||||
|
<a href="https://docs.grid.space/kiri-moto/gcode-macros" target="docs">gcode macro docs</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,114 +0,0 @@
|
||||||
/** atom3dp css */
|
|
||||||
|
|
||||||
button {
|
|
||||||
color: #000;
|
|
||||||
border: 1px solid rgba(20,20,20,0.5);
|
|
||||||
background-color: rgba(210,210,210,0.8);
|
|
||||||
padding: 2px 7px 3px 7px;
|
|
||||||
margin-bottom: 2px !important;
|
|
||||||
}
|
|
||||||
button:hover {
|
|
||||||
border-color: #000;
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
border-bottom: 1px solid rgba(220,220,225,1);
|
|
||||||
}
|
|
||||||
.dialog {
|
|
||||||
background-color: rgba(220,220,220,0.75);
|
|
||||||
border-color: #bbb;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
#device-cols > div {
|
|
||||||
background-color: rgba(250,250,250,0.75);
|
|
||||||
}
|
|
||||||
#device-list select {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
#device-list option[local="1"] {
|
|
||||||
color: #00f;
|
|
||||||
}
|
|
||||||
#device-labels span {
|
|
||||||
background-color: rgba(170,221,255,0.75);
|
|
||||||
border: 1px dashed #aaa;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tool-cols > div {
|
|
||||||
background-color: rgba(250,250,250,0.75);
|
|
||||||
}
|
|
||||||
#tool-list select {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
#tool-list option[local="1"] {
|
|
||||||
color: #00f;
|
|
||||||
}
|
|
||||||
#tool-labels span {
|
|
||||||
background-color: rgba(170,221,255,0.75);
|
|
||||||
border: 1px dashed #aaa;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
#catalog span {
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
background-color: rgba(170,221,255,0.75);
|
|
||||||
border: 1px dashed #aaa;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
#catalog button {
|
|
||||||
background-color: rgba(250,250,250,0.8);
|
|
||||||
}
|
|
||||||
#catalog button:hover {
|
|
||||||
background-color: rgba(200,200,200,0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
#settings span {
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
background-color: rgba(170,221,255,0.75);
|
|
||||||
border: 1px dashed #aaa;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
#settings button {
|
|
||||||
background-color: rgba(250,250,250,0.8);
|
|
||||||
}
|
|
||||||
#settings button:hover {
|
|
||||||
background-color: rgba(200,200,200,0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.grouphead {
|
|
||||||
color: black;
|
|
||||||
border-top-left-radius: 3px;
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
border-bottom-right-radius: 3px;
|
|
||||||
border-bottom-left-radius: 0;
|
|
||||||
border: 1px dashed #aaa;
|
|
||||||
margin-top: 5px;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
padding: 3px 2px 2px 3px;
|
|
||||||
background-color: rgba(170,221,255,0.75);
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
#control-left {
|
|
||||||
border-top: 0;
|
|
||||||
border-bottom: 0;
|
|
||||||
background-color: rgba(220,220,225,0.25);
|
|
||||||
}
|
|
||||||
#control-right {
|
|
||||||
color: #000;
|
|
||||||
border-top: 0;
|
|
||||||
border-bottom: 0;
|
|
||||||
background-color: rgba(220,220,225,0.25);
|
|
||||||
}
|
|
||||||
#appid span {
|
|
||||||
x-background-color: rgba(220,220,225,0.5) !important;
|
|
||||||
}
|
|
||||||
#selection span {
|
|
||||||
background-color: rgba(220,220,225,0.5) !important;
|
|
||||||
}
|
|
||||||
#layer-view span {
|
|
||||||
background-color: rgba(220,220,225,0.5) !important;
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
/** atom3dp css */
|
|
||||||
|
|
||||||
button {
|
|
||||||
color: #000;
|
|
||||||
border: 1px solid rgba(20,20,20,0.5);
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
border-bottom: 1px solid rgba(200,200,0,0.75);
|
|
||||||
}
|
|
||||||
.grouphead {
|
|
||||||
color: white;
|
|
||||||
background-color: rgba(0,0,0,0.85);
|
|
||||||
}
|
|
||||||
#control-left {
|
|
||||||
background-color: rgba(240,240,20,0.5);
|
|
||||||
}
|
|
||||||
#control-right {
|
|
||||||
color: #000;
|
|
||||||
background-color: rgba(240,240,20,0.5);
|
|
||||||
}
|
|
||||||
#appid span {
|
|
||||||
background-color: rgba(240,240,20,0.5) !important;
|
|
||||||
}
|
|
||||||
#selection span {
|
|
||||||
background-color: rgba(240,240,20,0.5) !important;
|
|
||||||
}
|
|
||||||
#layer-view span {
|
|
||||||
background-color: rgba(240,240,20,0.5) !important;
|
|
||||||
}
|
|
||||||
#modeCAM {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue