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) {
|
if (opt.wasm && geo.wasm) {
|
||||||
try {
|
try {
|
||||||
console.log({ wasm_union: polys, minarea });
|
// console.log({ wasm_union: polys, minarea });
|
||||||
if (minarea) polys = polys.filter(p => p.area() >= minarea);
|
if (minarea) polys = polys.filter(p => p.area() >= minarea);
|
||||||
let out = geo.wasm.js.union(polys, polys[0].getZ());
|
let out = geo.wasm.js.union(polys, polys[0].getZ());
|
||||||
opt.changes = length(out) - lpre;
|
opt.changes = length(out) - lpre;
|
||||||
|
|
|
||||||
|
|
@ -455,7 +455,7 @@ export const conf = {
|
||||||
camContourTool: 1000,
|
camContourTool: 1000,
|
||||||
camContourXOn: true,
|
camContourXOn: true,
|
||||||
camContourYOn: true,
|
camContourYOn: true,
|
||||||
camDepthFirst: false,
|
camDepthFirst: true,
|
||||||
camDrillDown: 5,
|
camDrillDown: 5,
|
||||||
camDrillDownSpeed: 250,
|
camDrillDownSpeed: 250,
|
||||||
camDrillDwell: 250,
|
camDrillDwell: 250,
|
||||||
|
|
@ -472,7 +472,7 @@ export const conf = {
|
||||||
camExpertFast: false,
|
camExpertFast: false,
|
||||||
camFastFeed: 6000,
|
camFastFeed: 6000,
|
||||||
camFastFeedZ: 300,
|
camFastFeedZ: 300,
|
||||||
camFirstZMax: false,
|
camFirstZMax: true,
|
||||||
camFlatness: 0.001,
|
camFlatness: 0.001,
|
||||||
camFlipAxis: "X",
|
camFlipAxis: "X",
|
||||||
camFlipOther: "",
|
camFlipOther: "",
|
||||||
|
|
|
||||||
|
|
@ -959,7 +959,9 @@ class Widget {
|
||||||
.add(a[1].x, a[1].y, a[1].z)
|
.add(a[1].x, a[1].y, a[1].z)
|
||||||
.add(a[2].x, a[2].y, a[2].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
|
// for a more perfect union, pump shadows to merge very close lines
|
||||||
// todo: create clipper only version that avoids round trip thru geo classes
|
// 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
|
// Widget Grouping API
|
||||||
const Group = Widget.Groups = {
|
const Group = Widget.Groups = {
|
||||||
list() {
|
list() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue