From 511f66571a7c025cadbed87896f44fd5c6ef9e70 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Wed, 11 Jan 2023 12:48:43 -0500 Subject: [PATCH] factor out rastering so i can be distributed to minions --- src/kiri-mode/cam/ops.js | 5 +- src/kiri-mode/cam/topo.js | 220 ++++++++++++++++++++------------------ 2 files changed, 120 insertions(+), 105 deletions(-) diff --git a/src/kiri-mode/cam/ops.js b/src/kiri-mode/cam/ops.js index 9a4072c7..fc606614 100644 --- a/src/kiri-mode/cam/ops.js +++ b/src/kiri-mode/cam/ops.js @@ -771,7 +771,10 @@ class OpContour extends CamOp { printPoint = newPoint(bounds.min.x,bounds.min.y,zmax); for (let slice of sliceOut) { - if (!slice.camLines) continue; + // ignore debug slices + if (!slice.camLines) { + continue; + } let polys = [], poly, emit; slice.camLines.forEach(function (poly) { if (depthFirst) poly = poly.clone(true); diff --git a/src/kiri-mode/cam/topo.js b/src/kiri-mode/cam/topo.js index 22ff0b4c..1e6e7533 100644 --- a/src/kiri-mode/cam/topo.js +++ b/src/kiri-mode/cam/topo.js @@ -212,127 +212,48 @@ class Topo { lastP = undefined; } - function raster(slices) { + function rastering(slices) { if (!topo.raster) { console.log(widget.id, 'topo raster cached'); return topo.box; } + topo.raster = false; + topo.box = new THREE.Box2(); - let gridx = 0, - gridy, - gridi, // index - gridv, // value - i, il, j, jl, x, y, tv, ltv, - box = topo.box = new THREE.Box2(); - - // filter lines pairs to only surface "up-facing", "uncovered" lines - slices.map(slice => { + let gridx = 0; + for (let slice of slices) { newslices.push(slice); - const points = []; - // emit an array of valid line-pairs - const lines = slice.lines; - const len = lines.length; - outer: for (let i=0; i p2.y) { const tp = p1; p1 = p2; p2 = tp }; - // eliminate if points "under" other lines - for (let j=0; j= i-1 && j <= i+1) continue; - let l2 = lines[j], p3 = l2.p1, p4 = l2.p2; - // sort p3,p4 by y for comparison - if (p3.y > p4.y) { const tp = p3; p3 = p4; p4 = tp }; - // it's under the other line - if (Math.max(p1.z,p2.z) < Math.min(p3.z,p4.z)) { - // it's inside the other line, too, so skip - if (p1.y >= p3.y && p2.y <= p4.y) continue outer; - } - } - points.push(p1, p2); - box.expandByPoint(p1); - box.expandByPoint(p2); - } - slice.points = points; - if (debug_topo_lines) slice.output() - .setLayer("topo lines", {face: 0xff00ff, line: 0x880088}) - .addLines(points); - if (debug_topo_shells) slice.output() - .setLayer("topo shells", {face: 0xff00ff, line: 0x008888}) - .addPolys(slice.topPolys()); - }); - - // raster grid: for each Y slice, find z grid value (x/z swapped) - for (j=0, jl=slices.length; j gridv || p2.z > gridv); - // segment crosses grid y - const spansy = (p1.y <= y && p2.y >= y); - if (crossz && spansy) { - // compute intersection of z ray up - // and segment at this grid point - const dy = p1.y - p2.y, - dz = p1.z - p2.z, - pct = (p1.y - y) / dy, - nz = p1.z - (dz * pct); - // save if point is greater than existing grid point - if (nz > gridv) { - gridv = data[gridi] = Math.max(nz, zMin); - if (debug_topo) slice.output() - .setLayer("heights", {face: color, line: color}) - .addLine( - newPoint(p1.x, y, 0), - newPoint(p1.x, y, gridv) - ); - } - } - } - gridy++; - } - gridx++; - // remove flat lines when curvesOnly - if (curvesOnly) { - let nup = []; - for (let i=0, p=slice.points, l=p.length; i= flatness) { - nup.push(p1, p2); - } - } - slice.points = nup; - } + slice.points = raster_slice({ + lines: slice.lines, + box: topo.box, + data, + resolution, + curvesOnly, + flatness, + zMin, + minY, + maxY, + stepsy, + slice, + gridx: gridx++ + }); onupdate(++stepsTaken, stepsTotal, "raster surface"); } - return box; } - function processSlices(slices) { + function contouring(slices) { let gridx = 0, gridy, gridi, // index gridv, // value i, il, j, jl, x, y, tv, ltv; - const box = raster(slices).expandByVector(new THREE.Vector3( + const box = topo.box.expandByVector(new THREE.Vector3( partOff, partOff, 0 )); + const checkr = newPoint(0,0); const inClip = function(polys, checkZ) { checkr.x = x; @@ -437,13 +358,13 @@ class Topo { onupdate(++stepsTaken, stepsTotal, "contour x"); } } - - ondone(newslices); } const slices2 = await this.topo_slice(widget, resolution); - processSlices(slices2); + rastering(slices2); + contouring(slices2); + ondone(newslices); return this; } @@ -554,6 +475,97 @@ class Topo { } } +function raster_slice(inputs) { + const { lines, data, box, resolution, curvesOnly } = inputs; + const { flatness, zMin, minY, maxY, stepsy, gridx } = inputs; + const { slice } = inputs; + + let gridy, + gridi, // index + gridv, // value + i, il, j, jl, x, y, tv, ltv; + + // filter lines pairs to only surface "up-facing", "uncovered" lines + const points = []; + // emit an array of valid line-pairs + const len = lines.length; + + outer: for (let i=0; i p2.y) { const tp = p1; p1 = p2; p2 = tp }; + // eliminate if points "under" other lines + for (let j=0; j= i-1 && j <= i+1) continue; + let l2 = lines[j], p3 = l2.p1, p4 = l2.p2; + // sort p3,p4 by y for comparison + if (p3.y > p4.y) { const tp = p3; p3 = p4; p4 = tp }; + // it's under the other line + if (Math.max(p1.z,p2.z) < Math.min(p3.z,p4.z)) { + // it's inside the other line, too, so skip + if (p1.y >= p3.y && p2.y <= p4.y) continue outer; + } + } + points.push(p1, p2); + box.expandByPoint(p1); + box.expandByPoint(p2); + } + + gridy = 0; + // rasterize one x slice + for (y = minY; y < maxY && gridy < stepsy; y += resolution) { + gridi = gridx * stepsy + gridy; + gridv = data[gridi] || 0; + // strategy using raw lines (faster slice, but more lines) + for (i=0, il=points.length; i gridv || p2.z > gridv); + // segment crosses grid y + const spansy = (p1.y <= y && p2.y >= y); + if (crossz && spansy) { + // compute intersection of z ray up + // and segment at this grid point + const dy = p1.y - p2.y, + dz = p1.z - p2.z, + pct = (p1.y - y) / dy, + nz = p1.z - (dz * pct); + // save if point is greater than existing grid point + if (nz > gridv) { + gridv = data[gridi] = Math.max(nz, zMin); + if (slice) slice.output() + .setLayer("heights", {face: 0, line: 0}) + .addLine( + newPoint(p1.x, y, 0), + newPoint(p1.x, y, gridv) + ); + } + } + } + gridy++; + } + + // remove flat lines when curvesOnly + if (curvesOnly) { + let nup = []; + for (let i=0, p=points, l=p.length; i= flatness) { + nup.push(p1, p2); + } + } + points = nup; + } + + return points; +}; + CAM.Topo = async function(opt) { return new Topo().generate(opt); };