add tab support in contouring

This commit is contained in:
Stewart Allen 2020-11-14 13:19:37 -05:00
commit a66a794f14
4 changed files with 61 additions and 35 deletions

View file

@ -3,7 +3,6 @@
## 2.3 remaining ## 2.3 remaining
* adaptive shadow-line generation for small parts collision detection * adaptive shadow-line generation for small parts collision detection
* test path clearance for every move > % of tool diam and ... * test path clearance for every move > % of tool diam and ...
* contour tabs support
* path arrows, retracts, and engages * path arrows, retracts, and engages
* cap path ends * cap path ends
* help dialog * help dialog

View file

@ -1507,7 +1507,7 @@
camDrillingOn: UC.newBoolean(LANG.enable, onBooleanClick, {modes:CAM}), camDrillingOn: UC.newBoolean(LANG.enable, onBooleanClick, {modes:CAM}),
camDrillSep: UC.newBlank({class:"pop-sep"}), camDrillSep: UC.newBlank({class:"pop-sep"}),
camDrillReg: UC.newSelect(LANG.cd_regi_s, {modes:CAM, title:LANG.cd_regi_l}, "drillreg"), camDrillReg: UC.newSelect(LANG.cd_regi_s, {modes:CAM, title:LANG.cd_regi_l}, "drillreg"),
camTabs: UC.newGroup(LANG.ct_menu, null, {modes:CAM, marker:true, show:() => { return UI.camOutlineOn.checked || UI.camRoughOn.checked }}), camTabs: UC.newGroup(LANG.ct_menu, null, {modes:CAM, marker:true}),
camTabsAngle: UC.newInput(LANG.ct_angl_s, {title:LANG.ct_angl_l, convert:UC.toInt, bound:UC.bound(0,360), modes:CAM}), camTabsAngle: UC.newInput(LANG.ct_angl_s, {title:LANG.ct_angl_l, convert:UC.toInt, bound:UC.bound(0,360), modes:CAM}),
camTabsCount: UC.newInput(LANG.ct_numb_s, {title:LANG.ct_numb_l, convert:UC.toInt, bound:UC.bound(1,20), modes:CAM}), camTabsCount: UC.newInput(LANG.ct_numb_s, {title:LANG.ct_numb_l, convert:UC.toInt, bound:UC.bound(1,20), modes:CAM}),
camTabsWidth: UC.newInput(LANG.ct_wdth_s, {title:LANG.ct_wdth_l, convert:UC.toFloat, bound:UC.bound(0.1,100), modes:CAM, units:true}), camTabsWidth: UC.newInput(LANG.ct_wdth_s, {title:LANG.ct_wdth_l, convert:UC.toFloat, bound:UC.bound(0.1,100), modes:CAM, units:true}),

View file

@ -469,43 +469,30 @@
} }
// cut outside traces at the right points // cut outside traces at the right points
function addCutoutTabs(offset, z, toolDiam, tabWidth, tabCount, tabAngle) { function addCutoutTabs(polys, z, toolDiam, tabWidth, tabCount, tabAngle) {
// skip if no tops | traces // skip if no tops | traces
if (offset.length === 0) return offset; if (polys.length === 0) return polys;
let notabs = 0; let notabs = 0;
let nutrace = []; let nutrace = [];
// find trace with greatest area polys.forEach(function(trace, index) {
offset.forEach(function(trace, index) {
// required to match computed order of cutouts // required to match computed order of cutouts
trace.setClockwise(); trace.setClockwise();
let count = tabCount, let ints = [];
angle = tabAngle, let center = trace.bounds.center(z);
angle_inc = 360 / count, CAM.createTabLines(center, toolDiam, tabWidth, tabCount, tabAngle).forEach(tab => {
center = trace.bounds.center(z), const {c1, c2, o1, o2} = tab,
offset = (tabWidth + toolDiam) / 2,
ints = [],
segs = [];
while (count-- > 0) {
let slope = BASE.newSlopeFromAngle(angle),
normal = BASE.newSlopeFromAngle(angle + 90),
c1 = center.projectOnSlope(normal, offset),
c2 = center.projectOnSlope(normal, -offset),
o1 = c1.projectOnSlope(slope, 10000),
o2 = c2.projectOnSlope(slope, 10000),
int1 = trace.intersections(c1, o1).pop(), int1 = trace.intersections(c1, o1).pop(),
int2 = trace.intersections(c2, o2).pop(); int2 = trace.intersections(c2, o2).pop();
if (int1 && int2) { if (int1 && int2) {
ints.push(int1); ints.push(int1);
ints.push(int2); ints.push(int2);
} }
angle -= angle_inc; });
}
let segs = [];
if (ints.length) { if (ints.length) {
ints.push(ints.shift()); ints.push(ints.shift());
for (let i=0; i<ints.length; i+=2) { for (let i=0; i<ints.length; i+=2) {
@ -529,7 +516,6 @@
nutrace.push(trace); nutrace.push(trace);
notabs++; notabs++;
} }
}); });
if (notabs) { if (notabs) {
@ -539,4 +525,23 @@
return nutrace; return nutrace;
} }
CAM.createTabLines = function(center, toolDiam, tabWidth, tabCount, tabAngle) {
let angle_inc = 360 / tabCount,
offset = (tabWidth + toolDiam) / 2,
lines = [];
while (tabCount-- > 0) {
let slope = BASE.newSlopeFromAngle(tabAngle),
normal = BASE.newSlopeFromAngle(tabAngle + 90),
c1 = center.projectOnSlope(normal, offset),
c2 = center.projectOnSlope(normal, -offset),
o1 = c1.projectOnSlope(slope, 10000),
o2 = c2.projectOnSlope(slope, 10000);
tabAngle -= angle_inc;
lines.push({c1, o1, c2, o2});
}
return lines;
}
})(); })();

View file

@ -56,12 +56,30 @@
widget: widget widget: widget
}, },
newslices = [], newslices = [],
tabsOn = proc.camTabsOn,
tabHeight = proc.camTabsHeight,
clipTab = tabsOn ? [] : null,
clipTo = inside ? shadow : POLY.expand(shadow, toolDiameter + resolution), clipTo = inside ? shadow : POLY.expand(shadow, toolDiameter + resolution),
partOff = inside ? 0 : toolDiameter / 2 + resolution, partOff = inside ? 0 : toolDiameter / 2 + resolution,
gridDelta = Math.floor(partOff / resolution); gridDelta = Math.floor(partOff / resolution);
let newlines, if (proc.camTabsOn) {
newtop, CAM.createTabLines(
clipTo[0].bounds.center(),
toolDiameter,
proc.camTabsWidth,
proc.camTabsCount,
proc.camTabsAngle
).forEach(tab => {
const { o1, o2, c1, c2 } = tab;
const poly = newPolygon().addPoints([
o1, c1, c2, o2
]);
clipTab.push(poly);
});
}
let newtop,
newtrace, newtrace,
sliceout, sliceout,
latent, latent,
@ -174,16 +192,16 @@
} }
const checkr = newPoint(0,0); const checkr = newPoint(0,0);
const inClip = clipTo ? function() { const inClip = function(polys) {
checkr.x = x; checkr.x = x;
checkr.y = y; checkr.y = y;
for (let i=0; i<clipTo.length; i++) { for (let i=0; i<polys.length; i++) {
if (checkr.isInPolygon(clipTo[i])) { if (checkr.isInPolygon(polys[i])) {
return true; return true;
} }
} }
return false; return false;
} : function() { return true }; };
// x contouring // x contouring
if (proc.camContourXOn) { if (proc.camContourXOn) {
@ -194,13 +212,15 @@
ly = gridy = -gridDelta; ly = gridy = -gridDelta;
slice = newSlice(gridx); slice = newSlice(gridx);
slice.camMode = PRO.CONTOUR_X; slice.camMode = PRO.CONTOUR_X;
// slice.lines = newlines = [];
newtop = slice.addTop(newPolygon().setOpen()).poly; newtop = slice.addTop(newPolygon().setOpen()).poly;
newtrace = newPolygon().setOpen(); newtrace = newPolygon().setOpen();
sliceout = []; sliceout = [];
for (y = minY - partOff; y < maxY + partOff; y += resolution) { for (y = minY - partOff; y < maxY + partOff; y += resolution) {
tv = toolTipZ(gridx, gridy); tv = toolTipZ(gridx, gridy);
if (tv === 0 && clipTo && !inClip()) { if (tabsOn && tv < tabHeight && inClip(clipTab)) {
tv = tabHeight;
}
if (tv === 0 && clipTo && !inClip(clipTo)) {
end_poly(); end_poly();
gridy++; gridy++;
ly = -gridDelta; ly = -gridDelta;
@ -245,13 +265,15 @@
lx = gridx = -gridDelta; lx = gridx = -gridDelta;
slice = newSlice(gridy); slice = newSlice(gridy);
slice.camMode = PRO.CONTOUR_Y; slice.camMode = PRO.CONTOUR_Y;
// slice.lines = newlines = [];
newtop = slice.addTop(newPolygon().setOpen()).poly; newtop = slice.addTop(newPolygon().setOpen()).poly;
newtrace = newPolygon().setOpen(); newtrace = newPolygon().setOpen();
sliceout = []; sliceout = [];
for (x = minX - partOff; x <= maxX + partOff; x += resolution) { for (x = minX - partOff; x <= maxX + partOff; x += resolution) {
tv = toolTipZ(gridx, gridy); tv = toolTipZ(gridx, gridy);
if (tv === 0 && clipTo && !inClip()) { if (tabsOn && tv < tabHeight && inClip(clipTab)) {
tv = tabHeight;
}
if (tv === 0 && clipTo && !inClip(clipTo)) {
end_poly(); end_poly();
gridx++; gridx++;
lx = -gridDelta; lx = -gridDelta;