diff --git a/src/kiri-mode/laser/driver.js b/src/kiri-mode/laser/driver.js index 3907c4c7..51fe5e4f 100644 --- a/src/kiri-mode/laser/driver.js +++ b/src/kiri-mode/laser/driver.js @@ -328,10 +328,10 @@ async function prepare(widgets, settings, update) { } // compute tile width / height - for (let layerout of output) { + for (let layer of output) { let min = {w:Infinity, h:Infinity}, max = {w:-Infinity, h:-Infinity}, p; // compute bounding box for each layer - for (let out of layerout) { + for (let out of layer) { p = out.point; out.point = p.clone(); // b/c first/last point are often shared min.w = Math.min(min.w, p.x); @@ -339,10 +339,10 @@ async function prepare(widgets, settings, update) { min.h = Math.min(min.h, p.y); max.h = Math.max(max.h, p.y); } - layerout.w = max.w - min.w; - layerout.h = max.h - min.h; + layer.w = max.w - min.w; + layer.h = max.h - min.h; // shift objects to top/left of w/h box bounds - for (let out of layerout) { + for (let out of layer) { p = out.point; p.x -= min.w; p.y -= min.h; @@ -356,13 +356,13 @@ async function prepare(widgets, settings, update) { spacing = process.ctOutTileSpacing, // sort objects by size when not using laser layer ordering c = sort ? output.sort() : output, - p = new kiri.Pack(dw, dh, spacing, isWire).fit(c, !sort); + p = new kiri.Pack(dw, dh, spacing, {invy:isWire}).fit(c, !sort); // test different ratios until packed while (!p.packed) { dw *= 1.1; dh *= 1.1; - p = new kiri.Pack(dw, dh, spacing, isWire).fit(c ,!sort); + p = new kiri.Pack(dw, dh, spacing, {invy:isWire}).fit(c ,!sort); } // update packed tile with new location @@ -392,62 +392,91 @@ function exportLaser(print, online, ondone) { * */ function exportElements(settings, output, onpre, onpoly, onpost, onpoint, onlayer) { - let process = settings.process, - zcolor = process.ctOutZColor, + let { process, device } = settings, + { bedWidth, bedDepth } = device, + { ctOriginCenter, ctOriginBounds } = process, + { outputInvertX, outputInvertY } = process, + { ctOriginOffX, ctOriginOffY } = process, last, point, poly = [], + off = {x:ctOriginOffX||0, y:ctOriginOffY||0}, min = {x:0, y:0}, - max = {x:0, y:0}; + max = {x:0, y:0}, + size = {w:0, h:0}; - output.forEach(function(layer) { - layer.forEach(function(out) { + // compute bounds for entire output + output.forEach(layer => { + layer.forEach(out => { point = out.point; - if (process.outputInvertX) point.x = -point.x; - if (process.outputInvertY) point.y = -point.y; + if (outputInvertX) point.x = -point.x; + if (outputInvertY) point.y = -point.y; min.x = Math.min(min.x, point.x); max.x = Math.max(max.x, point.x); min.y = Math.min(min.y, point.y); max.y = Math.max(max.y, point.y); }); }); + size.w = max.x - min.x; + size.h = max.y - min.y; + console.log('export bounds', min, max, size); - if (!process.ctOriginCenter) { - // normalize against origin lower left - output.forEach(function(layer) { - layer.forEach(function(out) { + let bounds = base.newBounds(); + if (ctOriginCenter) { + // place origin at geometric center of all points + // regardless of workspace size + for (let layer of output) { + for (let out of layer) { point = out.point; - point.x -= min.x; - point.y -= min.y; - }); - }); - max.x = max.x - min.x; - max.y = max.y - min.y; + point.x = point.x - min.x - size.w / 2 + off.x; + point.y = point.y - min.y - size.h / 2 + off.y; + bounds.update(point); + } + } + max.x = max.x - min.x + off.x; + max.y = max.y - min.y + off.y; + min.x = 0; + min.y = 0; + } else if (ctOriginBounds) { + // place origin at min x,y of all points + for (let layer of output) { + for (let out of layer) { + point = out.point; + point.x = point.x - min.x + ctOriginOffX; + point.y = point.y - min.y + ctOriginOffY; + bounds.update(point); + } + } + max.x = max.x - min.x + off.x; + max.y = max.y - min.y + off.y; min.x = 0; min.y = 0; } else { - // normalize against center of build area - let w = settings.device.bedWidth; - let h = settings.device.bedDepth; - output.forEach(function(layer) { - layer.forEach(function(out) { + // place origin at min x,y taking into account + // each layer's relative position + let w = bedWidth; + let h = bedDepth; + for (let layer of output) { + for (let out of layer) { point = out.point; - point.x += w/2; - point.y += h/2; - }); - }); - max.x = w; - max.y = h; + point.x += w / 2 + off.x; + point.y += h / 2 + off.y; + bounds.update(point); + } + } + max.x = w + off.x; + max.y = h + off.y; min.x = 0; min.y = 0; } onpre(min, max, process.ctOutPower, process.ctOutSpeed); - output.forEach(function(layer, index) { + // output each layer with moves between them + output.forEach((layer, index) => { let thick = 0; let color = 0; - layer.forEach(function(out, li) { + layer.forEach((out, li) => { thick = out.thick; point = out.point; if (onlayer) { diff --git a/src/kiri/pack.js b/src/kiri/pack.js index 53b7fd1a..a685ebd0 100644 --- a/src/kiri/pack.js +++ b/src/kiri/pack.js @@ -12,37 +12,47 @@ gapp.register("kiri.pack", [], (root, exports) => { const { kiri } = root; class Packer { - constructor(w, h, spacing, inv) { + constructor(w, h, spacing, opt = {}) { this.root = { x: 0, y: 0, w: w, h: h }; this.max = { w: 0, h: 0 }; this.packed = false; this.spacing = typeof(spacing) === 'number' ? spacing : 1; - this.inv = inv; + this.opt = opt; this.pad = this.spacing / 2; } + // array of blocks/tiles with {w,h} properties simple(blocks) { - let n = 0, block, x = 0, y = 0, mh = 0; + let n = 0, block, x = 0, y = 0, mh = 0, maxx = 0, maxy = 0; let spacing = blocks.length > 1 ? this.spacing : 0; while (n < blocks.length) { block = blocks[n++]; block.fit = { x, y }; this.max.w = Math.max(this.max.w, x + block.w); this.max.h = Math.max(this.max.h, y + block.h); + maxx = Math.max(maxx, x); + maxy = Math.max(maxy, y); mh = Math.max(mh, block.h); x += block.w + spacing; if (x > this.root.w) { x = 0; - y += ((mh + spacing) * (this.inv ? -1 : 1)); + y = y + mh + spacing; mh = 0; } - if (this.inv && (y < -this.root.h)) { - return this; - } if (y > this.root.h) { return this; } } + if (this.opt.invx) { + for (let block of blocks) { + block.fit.x = maxx - block.fit.x; + } + } + if (this.opt.invy) { + for (let block of blocks) { + block.fit.y = maxy - block.fit.y; + } + } this.packed = true; return this; } diff --git a/src/kiri/platform.js b/src/kiri/platform.js index f998fc67..9bd32ff8 100644 --- a/src/kiri/platform.js +++ b/src/kiri/platform.js @@ -93,16 +93,15 @@ function platformUpdateOrigin(update_bounds = true) { origin.x += process.camOriginOffX; origin.y += process.camOriginOffY; origin.z += process.camOriginOffZ; + if (isIndexed) { + origin.y = 0; + } } // WireEDM origin offsets if (MODE === MODES.WEDM) { origin.x -= process.ctOriginOffX; - origin.y -= process.ctOriginOffY; - } - - if (isIndexed) { - origin.y = 0; + origin.y += process.ctOriginOffY; } space.platform.setRulers(ruler, ruler, 1 / api.view.unit_scale(), 'X', isBelt ? 'Z' : 'Y'); diff --git a/web/kiri/index.css b/web/kiri/index.css index 6cef5f89..606965c9 100644 --- a/web/kiri/index.css +++ b/web/kiri/index.css @@ -275,7 +275,9 @@ th, tr, td, label { .dark #slider-max, .dark .mdialog, .dark .t-body, -.dark .cam-pop-op +.dark .cam-pop-op, +.dark #mod-print, +.dark #mod-print .header label { background-color: #222; color: white;