factor out rastering so i can be distributed to minions
This commit is contained in:
parent
9502a07c62
commit
511f66571a
2 changed files with 120 additions and 105 deletions
|
|
@ -771,7 +771,10 @@ class OpContour extends CamOp {
|
||||||
printPoint = newPoint(bounds.min.x,bounds.min.y,zmax);
|
printPoint = newPoint(bounds.min.x,bounds.min.y,zmax);
|
||||||
|
|
||||||
for (let slice of sliceOut) {
|
for (let slice of sliceOut) {
|
||||||
if (!slice.camLines) continue;
|
// ignore debug slices
|
||||||
|
if (!slice.camLines) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let polys = [], poly, emit;
|
let polys = [], poly, emit;
|
||||||
slice.camLines.forEach(function (poly) {
|
slice.camLines.forEach(function (poly) {
|
||||||
if (depthFirst) poly = poly.clone(true);
|
if (depthFirst) poly = poly.clone(true);
|
||||||
|
|
|
||||||
|
|
@ -212,127 +212,48 @@ class Topo {
|
||||||
lastP = undefined;
|
lastP = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function raster(slices) {
|
function rastering(slices) {
|
||||||
if (!topo.raster) {
|
if (!topo.raster) {
|
||||||
console.log(widget.id, 'topo raster cached');
|
console.log(widget.id, 'topo raster cached');
|
||||||
return topo.box;
|
return topo.box;
|
||||||
}
|
}
|
||||||
|
|
||||||
topo.raster = false;
|
topo.raster = false;
|
||||||
|
topo.box = new THREE.Box2();
|
||||||
|
|
||||||
let gridx = 0,
|
let gridx = 0;
|
||||||
gridy,
|
for (let slice of slices) {
|
||||||
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 => {
|
|
||||||
newslices.push(slice);
|
newslices.push(slice);
|
||||||
const points = [];
|
slice.points = raster_slice({
|
||||||
// emit an array of valid line-pairs
|
lines: slice.lines,
|
||||||
const lines = slice.lines;
|
box: topo.box,
|
||||||
const len = lines.length;
|
data,
|
||||||
outer: for (let i=0; i<len; i++) {
|
resolution,
|
||||||
let l1 = lines[i], p1 = l1.p1, p2 = l1.p2;
|
curvesOnly,
|
||||||
// eliminate vertical
|
flatness,
|
||||||
if (Math.abs(p1.y - p2.y) < flatness) continue;
|
zMin,
|
||||||
// eliminate if both points below cutoff
|
minY,
|
||||||
if (p1.z < zMin && p2.z < zMin) continue;
|
maxY,
|
||||||
// sort p1,p2 by y for comparison
|
stepsy,
|
||||||
if (p1.y > p2.y) { const tp = p1; p1 = p2; p2 = tp };
|
slice,
|
||||||
// eliminate if points "under" other lines
|
gridx: gridx++
|
||||||
for (let j=0; j<len; j++) {
|
|
||||||
// skip self and adjacent
|
|
||||||
if (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<jl; j++) {
|
|
||||||
const slice = slices[j];
|
|
||||||
const points = slice.points;
|
|
||||||
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<il; i += 2) {
|
|
||||||
const p1 = points[i], p2 = points[i+1];
|
|
||||||
// one endpoint above grid
|
|
||||||
const crossz = (p1.z > 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<l; i += 2) {
|
|
||||||
const p1 = p[i];
|
|
||||||
const p2 = p[i+1];
|
|
||||||
if (Math.abs(p1.z - p2.z) >= flatness) {
|
|
||||||
nup.push(p1, p2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
slice.points = nup;
|
|
||||||
}
|
|
||||||
onupdate(++stepsTaken, stepsTotal, "raster surface");
|
onupdate(++stepsTaken, stepsTotal, "raster surface");
|
||||||
}
|
}
|
||||||
|
|
||||||
return box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function processSlices(slices) {
|
function contouring(slices) {
|
||||||
let gridx = 0,
|
let gridx = 0,
|
||||||
gridy,
|
gridy,
|
||||||
gridi, // index
|
gridi, // index
|
||||||
gridv, // value
|
gridv, // value
|
||||||
i, il, j, jl, x, y, tv, ltv;
|
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
|
partOff, partOff, 0
|
||||||
));
|
));
|
||||||
|
|
||||||
const checkr = newPoint(0,0);
|
const checkr = newPoint(0,0);
|
||||||
const inClip = function(polys, checkZ) {
|
const inClip = function(polys, checkZ) {
|
||||||
checkr.x = x;
|
checkr.x = x;
|
||||||
|
|
@ -437,13 +358,13 @@ class Topo {
|
||||||
onupdate(++stepsTaken, stepsTotal, "contour x");
|
onupdate(++stepsTaken, stepsTotal, "contour x");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ondone(newslices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const slices2 = await this.topo_slice(widget, resolution);
|
const slices2 = await this.topo_slice(widget, resolution);
|
||||||
|
|
||||||
processSlices(slices2);
|
rastering(slices2);
|
||||||
|
contouring(slices2);
|
||||||
|
ondone(newslices);
|
||||||
|
|
||||||
return this;
|
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<len; i++) {
|
||||||
|
let l1 = lines[i], p1 = l1.p1, p2 = l1.p2;
|
||||||
|
// eliminate vertical
|
||||||
|
if (Math.abs(p1.y - p2.y) < flatness) continue;
|
||||||
|
// eliminate if both points below cutoff
|
||||||
|
if (p1.z < zMin && p2.z < zMin) continue;
|
||||||
|
// sort p1,p2 by y for comparison
|
||||||
|
if (p1.y > p2.y) { const tp = p1; p1 = p2; p2 = tp };
|
||||||
|
// eliminate if points "under" other lines
|
||||||
|
for (let j=0; j<len; j++) {
|
||||||
|
// skip self and adjacent
|
||||||
|
if (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<il; i += 2) {
|
||||||
|
const p1 = points[i], p2 = points[i+1];
|
||||||
|
// one endpoint above grid
|
||||||
|
const crossz = (p1.z > 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<l; i += 2) {
|
||||||
|
const p1 = p[i];
|
||||||
|
const p2 = p[i+1];
|
||||||
|
if (Math.abs(p1.z - p2.z) >= flatness) {
|
||||||
|
nup.push(p1, p2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
points = nup;
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
};
|
||||||
|
|
||||||
CAM.Topo = async function(opt) {
|
CAM.Topo = async function(opt) {
|
||||||
return new Topo().generate(opt);
|
return new Topo().generate(opt);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue