add optional shadow selection to area op
This commit is contained in:
parent
2d3042ce60
commit
9da2368a7a
5 changed files with 53 additions and 33 deletions
|
|
@ -443,6 +443,7 @@ export const conf = {
|
|||
camAreaExpand: 0,
|
||||
camAreaRefine: 0,
|
||||
camAreaSmooth: 1,
|
||||
camAreaShadow: false,
|
||||
camAreaDogbones: false,
|
||||
camAreaRevbones: false,
|
||||
camAreaOutline: false,
|
||||
|
|
|
|||
|
|
@ -669,6 +669,10 @@ export function createPopOps() {
|
|||
return env.poppedRec.mode === 'trace';
|
||||
}
|
||||
|
||||
function isShadow() {
|
||||
return env.poppedRec.shadow;
|
||||
}
|
||||
|
||||
function isSurface() {
|
||||
return env.poppedRec.mode === 'surface';
|
||||
}
|
||||
|
|
@ -697,6 +701,7 @@ export function createPopOps() {
|
|||
follow: 'camAreaFollow',
|
||||
refine: 'camAreaRefine',
|
||||
outline: 'camAreaOutline',
|
||||
shadow: 'camAreaShadow',
|
||||
tolerance: 'camTolerance',
|
||||
dogbones: 'camAreaDogbones',
|
||||
revbones: 'camAreaRevbones',
|
||||
|
|
@ -707,33 +712,39 @@ export function createPopOps() {
|
|||
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" }),
|
||||
exp: UC.newExpand("area selection", { open }),
|
||||
menu: UC.newRow([
|
||||
UC.newButton("edge", traceAdd),
|
||||
UC.newButton("surface", surfaceAdd),
|
||||
], { class: "ext-buttons f-row" }),
|
||||
], { class: "ext-buttons f-row", show: () => !isShadow() }),
|
||||
shadow: UC.newBoolean(LANG.cp_shad_s, undefined, { title: LANG.cp_shad_l }),
|
||||
outline: UC.newBoolean(LANG.cp_outl_s, undefined, { title: LANG.cp_outl_l }),
|
||||
exp_end: UC.endExpand(),
|
||||
sep: UC.newBlank({ class: "pop-sep" }),
|
||||
exp: UC.newExpand("area modifiers", { }),
|
||||
expand: UC.newInput(LANG.cp_xpnd_s, { title: LANG.cp_xpnd_l, convert: toFloat, units }),
|
||||
smooth: UC.newInput(LANG.cp_smoo_s, { title: LANG.cp_smoo_l, convert: toInt, xshow: isSurface }),
|
||||
follow: UC.newInput(LANG.cp_foll_s, { title: LANG.cp_foll_l, convert: toFloat }),
|
||||
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 }),
|
||||
exp_end: UC.endExpand(),
|
||||
exp: UC.newExpand("tool & stepping", { open }),
|
||||
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
|
||||
direction: UC.newSelect(LANG.ou_dire_s, { title: LANG.ou_dire_l }, "direction"),
|
||||
sr_angle: UC.newInput("step angle", { title: "step angle", convert: toFloat, bound: UC.bound(0, 360), show: isSurfaceLinear }),
|
||||
sr_angle: UC.newInput(LANG.ca_sang_s, { title: LANG.ca_sang_l, 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() }),
|
||||
refine: UC.newInput(LANG.cp_refi_s, { title: LANG.cp_refi_l, convert: toInt, show: isSurface }),
|
||||
sr_alter: UC.newBoolean("alternate", undefined, { title: "alternate cutting direction", show: isSurfaceLinear }),
|
||||
sr_alter: UC.newBoolean(LANG.ca_altr_s, undefined, { title: LANG.ca_altr_l, show: isSurfaceLinear }),
|
||||
dogbones: UC.newBoolean(LANG.co_dogb_s, undefined, { title: LANG.co_dogb_l, show: isTrace }),
|
||||
revbones: UC.newBoolean(LANG.co_dogr_s, undefined, { title: LANG.co_dogr_l, show: () => env.poppedRec.dogbones }),
|
||||
exp_end: UC.endExpand(),
|
||||
exp: UC.newExpand("feeds & speeds", { open }),
|
||||
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("bounds", { open }),
|
||||
exp: UC.newExpand("bounds", { }),
|
||||
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 }),
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class OpArea extends CamOp {
|
|||
let areaTool = new Tool(settings, tool);
|
||||
let smoothVal = (smooth ?? 0) / 10;
|
||||
let toolDiam = areaTool.fluteDiameter();
|
||||
let toolOver = areaTool.getStepSize(over);
|
||||
let toolOver = this.toolOver = areaTool.getStepSize(over);
|
||||
let zTop = workarea.top_z;
|
||||
let zBottom = workarea.bottom_z;
|
||||
let shadowBase = state.shadow.base;
|
||||
|
|
@ -71,6 +71,7 @@ class OpArea extends CamOp {
|
|||
}
|
||||
|
||||
// gather area selections
|
||||
if (!op.shadow)
|
||||
for (let arr of (op.areas[widget.id] ?? [])) {
|
||||
let poly = newPolygon().fromArray(arr);
|
||||
aminz = Math.min(aminz, poly.minZ());
|
||||
|
|
@ -86,22 +87,30 @@ class OpArea extends CamOp {
|
|||
polys = POLY.nest(POLY.reconnect(polys, false));
|
||||
|
||||
// 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 = [];
|
||||
for (let face of faces) {
|
||||
let i = face * 9;
|
||||
fpoly.push(newPolygon()
|
||||
.add(vert[i++], vert[i++], aminz = Math.min(aminz, vert[i++]))
|
||||
.add(vert[i++], vert[i++], aminz = Math.min(aminz, vert[i++]))
|
||||
.add(vert[i++], vert[i++], aminz = Math.min(aminz, vert[i++]))
|
||||
);
|
||||
}
|
||||
// remove invalid edges (eg. when vertical walls are the only selection)
|
||||
fpoly = fpoly.filter(p => p.area() > 0.001);
|
||||
if (!op.shadow) {
|
||||
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 = [];
|
||||
for (let face of faces) {
|
||||
let i = face * 9;
|
||||
fpoly.push(newPolygon()
|
||||
.add(vert[i++], vert[i++], aminz = Math.min(aminz, vert[i++]))
|
||||
.add(vert[i++], vert[i++], aminz = Math.min(aminz, vert[i++]))
|
||||
.add(vert[i++], vert[i++], aminz = Math.min(aminz, 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), aminz));
|
||||
// add in unioned surface areas
|
||||
polys.push(...POLY.setZ(POLY.union(fpoly, 0.00001, true), aminz));
|
||||
}
|
||||
|
||||
// use part shadow instead of areas or surfaces
|
||||
if (op.shadow) {
|
||||
console.log({ use_shadow_base: op.shadow });
|
||||
polys.push(...shadowBase.clone(true));
|
||||
}
|
||||
|
||||
// smoothing for jaggies usually caused by vertical walls
|
||||
if (smoothVal) {
|
||||
|
|
@ -343,7 +352,7 @@ class OpArea extends CamOp {
|
|||
}
|
||||
// optional alternating paths
|
||||
if (sr_alter) {
|
||||
paths = tip2tipJoin(paths, paths[0].first(), toolDiam * 4);
|
||||
paths = tip2tipJoin(paths, paths[0].first(), toolOver * 10);
|
||||
}
|
||||
} else
|
||||
if (sr_type === 'offset') {
|
||||
|
|
@ -392,6 +401,7 @@ class OpArea extends CamOp {
|
|||
raster.terminate();
|
||||
|
||||
// convert terrain raster output back to open polylines
|
||||
// todo: add leave_z support
|
||||
for (let path of output.paths) {
|
||||
path = newPolygon().fromArray([1, ...path]);
|
||||
if (op.refine) path.refine(op.refine);
|
||||
|
|
@ -417,14 +427,14 @@ class OpArea extends CamOp {
|
|||
}
|
||||
|
||||
prepare(ops, progress) {
|
||||
let { op, state, areas, surfaces } = this;
|
||||
let { op, state, areas, surfaces, toolOver } = this;
|
||||
let { newLayer, pocket, polyEmit, printPoint, tip2tipEmit } = ops;
|
||||
let { setContouring, setNextIsMove } = ops;
|
||||
let { process } = state.settings;
|
||||
|
||||
// process surface paths
|
||||
if (surfaces.length) {
|
||||
setContouring(true);
|
||||
setContouring(true, toolOver * 2);
|
||||
for (let surface of surfaces) {
|
||||
for (let poly of surface) {
|
||||
setNextIsMove();
|
||||
|
|
|
|||
|
|
@ -2,16 +2,12 @@
|
|||
|
||||
import { CamOp } from './op.js';
|
||||
import { OpArea } from './op-area.js';
|
||||
import { polygons as POLY } from '../../../geo/polygons.js';
|
||||
import { newPolygon } from '../../../geo/polygon.js';
|
||||
|
||||
class OpOutline extends CamOp {
|
||||
constructor(state, op) {
|
||||
super(state, op);
|
||||
}
|
||||
|
||||
// todo: wide cutout, dogbones
|
||||
|
||||
async slice(progress) {
|
||||
let { op, state } = this;
|
||||
let { direction, dogbones, down, inside, omitthru, omitvoid, outside } = op;
|
||||
|
|
@ -26,7 +22,6 @@ class OpOutline extends CamOp {
|
|||
let ops_list = this.ops_list = [ ];
|
||||
|
||||
if (outside) {
|
||||
// let areas = POLY.flatten(POLY.expand(shadow.base, state.tool.fluteDiameter() / 2 - 0.001));
|
||||
let areas = shadow.base.clone(true);
|
||||
ops_list.push(new OpArea(state, {
|
||||
areas: { [widget.id]: areas.map(p => p.toArray()) },
|
||||
|
|
@ -37,7 +32,6 @@ class OpOutline extends CamOp {
|
|||
mode: 'trace',
|
||||
omitinner: omitvoid,
|
||||
omitthru,
|
||||
// outline: omitthru,
|
||||
ov_botz,
|
||||
ov_topz,
|
||||
over: op.wide ? op.step : 0,
|
||||
|
|
@ -66,7 +60,6 @@ class OpOutline extends CamOp {
|
|||
omitinner: omitvoid,
|
||||
omitouter: inside,
|
||||
omitthru,
|
||||
// outline: omitthru,
|
||||
ov_botz,
|
||||
ov_topz,
|
||||
plunge,
|
||||
|
|
@ -80,9 +73,6 @@ class OpOutline extends CamOp {
|
|||
thru: true,
|
||||
tr_type: 'outside',
|
||||
}));
|
||||
if (!inside) {
|
||||
// add outline
|
||||
}
|
||||
}
|
||||
|
||||
for (let op of this.ops_list) {
|
||||
|
|
|
|||
|
|
@ -606,6 +606,8 @@ self.lang['en-us'] = {
|
|||
cp_cont_l: ["ignore interior voids and features"],
|
||||
cp_outl_s: "outline only",
|
||||
cp_outl_l: ["ignore interior voids and features"],
|
||||
cp_shad_s: "shadow",
|
||||
cp_shad_l: ["select part shadow as work area. overrides selected edges and surface areas"],
|
||||
|
||||
// CNC DRILLING
|
||||
cd_menu: "drill",
|
||||
|
|
@ -718,6 +720,12 @@ self.lang['en-us'] = {
|
|||
cl_xpnd_s: "expand",
|
||||
cl_xpnd_l: ["grow starting radius for step down. radius is defined as the highest Z point measured from the X axis center of the part"],
|
||||
|
||||
// CNC AREA OP
|
||||
ca_altr_s: "alternate",
|
||||
ca_altr_l: "alternate direction of travel lines (zigzag)",
|
||||
ca_sang_s: "step angle",
|
||||
ca_sang_l: "crossing angle on the XY plane for contour lines",
|
||||
|
||||
// OUTPUT
|
||||
ou_menu: "output",
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue