speed up shadow with grid bucketed recursive union. could be moved to workers
This commit is contained in:
parent
645d73a53f
commit
4c4adf2cc5
3 changed files with 73 additions and 4 deletions
|
|
@ -442,7 +442,7 @@ export function union(polys, minarea, all, opt = {}) {
|
|||
|
||||
if (opt.wasm && geo.wasm) {
|
||||
try {
|
||||
console.log({ wasm_union: polys, minarea });
|
||||
// console.log({ wasm_union: polys, minarea });
|
||||
if (minarea) polys = polys.filter(p => p.area() >= minarea);
|
||||
let out = geo.wasm.js.union(polys, polys[0].getZ());
|
||||
opt.changes = length(out) - lpre;
|
||||
|
|
|
|||
|
|
@ -455,7 +455,7 @@ export const conf = {
|
|||
camContourTool: 1000,
|
||||
camContourXOn: true,
|
||||
camContourYOn: true,
|
||||
camDepthFirst: false,
|
||||
camDepthFirst: true,
|
||||
camDrillDown: 5,
|
||||
camDrillDownSpeed: 250,
|
||||
camDrillDwell: 250,
|
||||
|
|
@ -472,7 +472,7 @@ export const conf = {
|
|||
camExpertFast: false,
|
||||
camFastFeed: 6000,
|
||||
camFastFeedZ: 300,
|
||||
camFirstZMax: false,
|
||||
camFirstZMax: true,
|
||||
camFlatness: 0.001,
|
||||
camFlipAxis: "X",
|
||||
camFlipOther: "",
|
||||
|
|
|
|||
|
|
@ -959,7 +959,9 @@ class Widget {
|
|||
.add(a[1].x, a[1].y, a[1].z)
|
||||
.add(a[2].x, a[2].y, a[2].z);
|
||||
});
|
||||
polys = POLY.union(polys, 0, true, { wasm: false });
|
||||
|
||||
// recursively merge grid constrained subsets of triangles
|
||||
polys = unionTris(polys);
|
||||
|
||||
// for a more perfect union, pump shadows to merge very close lines
|
||||
// todo: create clipper only version that avoids round trip thru geo classes
|
||||
|
|
@ -970,6 +972,73 @@ class Widget {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* recursively process triangle soup from mesh by bucketing them
|
||||
* by grid cell locality with max depth. this minimizes the number
|
||||
* of progressive small unions. results in a few unions of larger polys.
|
||||
*/
|
||||
function unionTris(polys, depth = 0) {
|
||||
if (depth < 5 && polys.length > 1000) {
|
||||
// Calculate bounding box of all triangles
|
||||
let minX = Infinity, maxX = -Infinity;
|
||||
let minY = Infinity, maxY = -Infinity;
|
||||
for (let tri of polys) {
|
||||
for (let pt of tri.points) {
|
||||
minX = Math.min(minX, pt.x);
|
||||
maxX = Math.max(maxX, pt.x);
|
||||
minY = Math.min(minY, pt.y);
|
||||
maxY = Math.max(maxY, pt.y);
|
||||
}
|
||||
}
|
||||
|
||||
// Create NxN grid
|
||||
const gridSize = 3;
|
||||
const cellWidth = (maxX - minX) / gridSize;
|
||||
const cellHeight = (maxY - minY) / gridSize;
|
||||
|
||||
// Partition polygons into grid cells
|
||||
const grid = Array(gridSize).fill(0).map(() => Array(gridSize).fill(0).map(() => []));
|
||||
|
||||
for (let i = 0; i < polys.length; i++) {
|
||||
const poly = polys[i];
|
||||
// Use polygon centroid to assign to cell
|
||||
const bounds = poly.bounds;
|
||||
const cx = (bounds.minx + bounds.maxx) / 2;
|
||||
const cy = (bounds.miny + bounds.maxy) / 2;
|
||||
|
||||
// Clamp to grid bounds
|
||||
let gx = Math.floor((cx - minX) / cellWidth);
|
||||
let gy = Math.floor((cy - minY) / cellHeight);
|
||||
gx = Math.max(0, Math.min(gridSize - 1, gx));
|
||||
gy = Math.max(0, Math.min(gridSize - 1, gy));
|
||||
|
||||
grid[gx][gy].push(poly);
|
||||
}
|
||||
|
||||
// Union within each cell
|
||||
const cellResults = [];
|
||||
let totalInCell = 0;
|
||||
for (let gx = 0; gx < gridSize; gx++) {
|
||||
for (let gy = 0; gy < gridSize; gy++) {
|
||||
const cellPolys = grid[gx][gy];
|
||||
if (cellPolys.length > 0) {
|
||||
totalInCell += cellPolys.length;
|
||||
const cellUnion = unionTris(cellPolys, depth + 1);
|
||||
cellResults.push(...cellUnion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Union the cell results
|
||||
polys = unionTris(cellResults, depth + 1);
|
||||
|
||||
} else {
|
||||
polys = POLY.union(polys, 0, true, { wasm: false });
|
||||
}
|
||||
|
||||
return polys;
|
||||
}
|
||||
|
||||
// Widget Grouping API
|
||||
const Group = Widget.Groups = {
|
||||
list() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue