From d560dff74443f6524600649c58965feb483aa6a7 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sun, 22 Nov 2020 19:10:49 -0500 Subject: [PATCH] checkpoint manual support work --- src/mode/fdm/client.js | 71 +++++++++++++++++++++++++++--- src/mode/fdm/prepare.js | 2 +- src/mode/fdm/slice.js | 95 +++++++++++++++++++++++++---------------- 3 files changed, 124 insertions(+), 44 deletions(-) diff --git a/src/mode/fdm/client.js b/src/mode/fdm/client.js index 415dede9..8118ec30 100644 --- a/src/mode/fdm/client.js +++ b/src/mode/fdm/client.js @@ -10,6 +10,7 @@ FDM = KIRI.driver.FDM, SPACE, API, p1, p2, iw, + lastMode, lastView, alert = [], func = {}; @@ -17,9 +18,12 @@ API = api; SPACE = api.const.SPACE; api.event.on("mode.set", mode => { - if (mode !== 'FDM') { - clearAllWidgetSupports(); - } + lastMode = mode; + updateVisiblity(); + }); + api.event.on("view.set", view => { + lastView = view; + updateVisiblity(); }); api.event.on("settings.load", (settings) => { if (settings.mode !== 'FDM') return; @@ -50,6 +54,7 @@ api.event.on("fdm.supports.done", func.sdone = () => { delbox('intZ'); delbox('intW'); + delbox('supp'); api.hide.alert(alert); api.feature.hover = false; }); @@ -58,12 +63,37 @@ clearAllWidgetSupports(); API.conf.save(); }); + api.event.on("slice.begin", () => { + func.sdone(); + updateVisiblity(); + }); api.event.on("key.esc", () => { func.sdone() }); - // api.event.on("selection.rotate", (x,y,z) => { - // console.log('rotate', x,y,z); - // }); + api.event.on("selection.rotate", rot => { + const {x, y, z} = rot; + if (x || y) { + API.selection.widgets().forEach(widget => { + clearWidgetSupports(widget); + }); + API.conf.save(); + } else { + API.selection.widgets().forEach(widget => { + let ann = API.widgets.annotate(widget.id); + let sups = ann.support || []; + sups.forEach(sup => { + let wsup = widget.sups[sup.id]; + let vc = new THREE.Vector3(sup.x, sup.y, sup.z); + let m4 = new THREE.Matrix4(); + m4 = m4.makeRotationFromEuler(new THREE.Euler(x || 0, y || 0, z || 0)); + vc.applyMatrix4(m4); + wsup.box.position.x = wsup.x = sup.x = vc.x; + wsup.box.position.y = wsup.y = sup.y = vc.y; + wsup.box.position.z = wsup.z = sup.z = vc.z; + }); + }); + } + }); api.event.on("mouse.hover.up", int => { delbox('supp'); if (!iw) return; @@ -97,7 +127,10 @@ if (int && int.face && int.face.normal.z < -0.1) { dir.y = -1; } - let targets = api.widgets.meshes().append(SPACE.internals().platform); + let targets = api.widgets.meshes() + .append(SPACE.internals().platform) + .appendAll(activeSupports()) + ; let i2 = ray.intersectObjects(targets, false); if (i2 && i2.length > 0) { // prevent false matches close to origin of ray @@ -118,6 +151,18 @@ }); } + function activeSupports() { + const active = []; + API.widgets.all().forEach(widget => { + Object.values(widget.sups || {}).forEach(support => { + active.push(support.box); + support.box.support = true; + // console.log({support}); + }); + }); + return active; + } + function restoreSupports(widgets) { widgets.forEach(widget => { const supports = API.widgets.annotate(widget.id).support || []; @@ -137,6 +182,18 @@ } } + function updateVisiblity() { + API.widgets.all().forEach(w => { + setSupportVisiblity(w, lastMode === 'FDM' && lastView === API.const.VIEWS.ARRANGE); + }); + } + + function setSupportVisiblity(widget, bool) { + Object.values(widget.sups || {}).forEach(support => { + support.box.visible = bool; + }); + } + function clearAllWidgetSupports() { API.widgets.all().forEach(widget => { clearWidgetSupports(widget); diff --git a/src/mode/fdm/prepare.js b/src/mode/fdm/prepare.js index de0f29b3..6e8cacac 100644 --- a/src/mode/fdm/prepare.js +++ b/src/mode/fdm/prepare.js @@ -177,7 +177,7 @@ } // synthesize a support widget, if needed - if (process.sliceSupportEnable) { + { let swidget = KIRI.newWidget(); let sslices = swidget.slices = []; widgets.forEach(function(widget) { diff --git a/src/mode/fdm/slice.js b/src/mode/fdm/slice.js index 05ede65b..aefb5357 100644 --- a/src/mode/fdm/slice.js +++ b/src/mode/fdm/slice.js @@ -192,9 +192,6 @@ slice.solids = []; }); - let supportEnabled = spro.sliceSupportEnable && spro.sliceSupportDensity > 0.0, - supportMinArea = spro.sliceSupportArea; - // create shells and diff inner fillable areas forSlices(0.0, 0.2, function(slice) { let solid = ( @@ -245,12 +242,20 @@ } // calculations only relevant when supports are enabled - if (supportEnabled) { + // if (supportEnabled) { + { + let auto = spro.sliceSupportEnable && spro.sliceSupportDensity > 0.0, + minArea = spro.sliceSupportArea; + + const fixed = Object.values(settings.widget[widget.id].support || {}); + forSlices(0.7, 0.8, function(slice) { - if (slice.index > 0) doSupport(slice, spro.sliceSupportOffset, spro.sliceSupportSpan, spro.sliceSupportExtra, supportMinArea, spro.sliceSupportSize, spro.sliceSupportOffset, spro.sliceSupportGap); + if (slice.index > 0) { + doSupport(slice, spro, auto, fixed); + } }, "support"); forSlices(0.8, 0.9, function(slice) { - doSupportFill(slice, nozzleSize, spro.sliceSupportDensity, supportMinArea); + doSupportFill(slice, nozzleSize, spro.sliceSupportDensity, minArea); }, "support"); } @@ -794,17 +799,18 @@ }; /** - * calculate external overhangs requiring support - * this is done bottom-up - * - * @param {number} minOffset trigger for unsupported distance - * @param {number} maxBridge max length before mid supports added - * @param {number} expand outer support clip - * @param {number} offset inner support clip - * @param {number} gap layers between supports and part + * calculate external overhangs requiring support. + * this is done bottom-up except for fixed supports (manual) */ - function doSupport(slice, minOffset, maxBridge, expand, minArea, pillarSize, offset, gap) { - let min = minArea || 0.01, + function doSupport(slice, proc, auto, fixed) { + let minOffset = proc.sliceSupportOffset, + maxBridge = proc.sliceSupportSpan, + expand = proc.sliceSupportExtra, + minArea = proc.supportMinArea, + pillarSize = proc.sliceSupportSize, + offset = proc.sliceSupportOffset, + gap = proc.sliceSupportGap, + min = minArea || 0.01, size = (pillarSize || 1), mergeDist = size * 3, // pillar merge dist tops = slice.topPolys(), @@ -865,29 +871,47 @@ let supports = []; - // add offset solids to supports (or fill depending) - fill.forEachPair(function(p1,p2) { checkLineSupport(p1, p2, false) }); - // if (top.bridges) POLY.expand(top.bridges, -maxBridge/2, top.z, supports, 1); + // generate support polys from unsupported points + if (auto) (function() { + // add offset solids to supports (or fill depending) + fill.forEachPair(function(p1,p2) { checkLineSupport(p1, p2, false) }); + // if (top.bridges) POLY.expand(top.bridges, -maxBridge/2, top.z, supports, 1); - // skip the rest if no points or supports - if (!(points.length || supports.length)) return; + // skip the rest if no points or supports + if (!(points.length || supports.length)) return; - let pillars = []; + let pillars = []; - // TODO project points down instead of unioned pillars - // TODO merge point/rect into hull of next nearest (up to maxBridge/2 away) - // TODO eliminate unions in favor of progress hulling (using previous w/nearness) - // TODO align pillar diamond along line (when doing line checks) + // TODO project points down instead of unioned pillars + // TODO merge point/rect into hull of next nearest (up to maxBridge/2 away) + // TODO eliminate unions in favor of progress hulling (using previous w/nearness) + // TODO align pillar diamond along line (when doing line checks) - // for each point, create a bounding rectangle - points.forEach(function(point) { - pillars.push(BASE.newPolygon().centerRectangle(point, size/2, size/2)); - }); + // for each point, create a bounding rectangle + points.forEach(function(point) { + pillars.push(BASE.newPolygon().centerRectangle(point, size/2, size/2)); + }); - // merge pillars and replace with convex hull of outer points (aka smoothing) - pillars = POLY.union(pillars).forEach(function(pillar) { - supports.push(BASE.newPolygon().createConvexHull(pillar.points)); - }); + // merge pillars and replace with convex hull of outer points (aka smoothing) + pillars = POLY.union(pillars).forEach(function(pillar) { + supports.push(BASE.newPolygon().createConvexHull(pillar.points)); + }); + })(); + + if (supports.length === 0 && !(fixed && fixed.length)) { + return; + } + + if (fixed && fixed.length) { + fixed.forEach(sup => { + let zmin = sup.z - sup.dh / 2; + let zmax = sup.z + sup.dh / 2; + if (slice.z >= zmin || slice.z <= zmax) { + let center = BASE.newPoint(sup.x, sup.y, slice.z); + supports.push(BASE.newPolygon().centerRectangle(center, sup.dw, sup.dw)); + } + }); + } // return top.supports = supports; // then union supports @@ -924,8 +948,7 @@ down = down.down; depth++; } - - }; + } /** * @param {number} linewidth