mirror of
https://github.com/CNCKitchen/stlTexturizer.git
synced 2026-04-07 22:11:32 +00:00
fix: spatial index, decimation overflow, input validation, accessibility
Round 2 of performance and correctness improvements: - Spatial grid index for brush painting: forEachTriInSphere now queries only nearby grid cells instead of scanning all triangles. ~5.7x faster for brush operations on 68k+ tri meshes. - Decimation overflow fix: hasLinkViolation used a fixed 0x200000 multiplier for vertex-pair keys, overflowing at >2M vertices. Now uses dynamic multiplier based on actual vertex count. - Decimation determinant threshold: solveQ used absolute 1e-10 which fails for large coordinates. Now relative to matrix element magnitude. - 3MF triangle index validation: bounds-check all parsed indices against vertex count, throw clear error on corrupt files instead of silent NaN. - File size limit: reject files >500 MB before loading into memory, prevents browser tab crash on oversized files. - Accessibility: preset swatches now keyboard-navigable (role=button, tabindex=0, Enter/Space to select). Modal dialogs trap focus and close on Escape. - Ctrl+click straight line tool: click to set start point, Ctrl+click to paint a straight line between points. Ctrl+hover shows preview. - Precision masking available for radius brush mode. - Spatial grid rebuilt when entering/leaving precision mode.
This commit is contained in:
+27
-7
@@ -160,24 +160,44 @@ export function buildExclusionOverlayGeo(geometry, faceSet, invert = false) {
|
||||
const srcPos = geometry.attributes.position.array;
|
||||
const srcNrm = geometry.attributes.normal ? geometry.attributes.normal.array : null;
|
||||
const total = srcPos.length / 9; // total triangle count
|
||||
const count = invert ? total - faceSet.size : faceSet.size;
|
||||
const isArr = faceSet instanceof Uint8Array;
|
||||
|
||||
// Count included faces
|
||||
let setSize;
|
||||
if (isArr) {
|
||||
setSize = 0;
|
||||
for (let i = 0; i < faceSet.length; i++) if (faceSet[i]) setSize++;
|
||||
} else {
|
||||
setSize = faceSet.size;
|
||||
}
|
||||
const count = invert ? total - setSize : setSize;
|
||||
const outPos = new Float32Array(count * 9);
|
||||
const outNrm = srcNrm ? new Float32Array(count * 9) : null;
|
||||
let dst = 0;
|
||||
if (invert) {
|
||||
for (let t = 0; t < total; t++) {
|
||||
if (faceSet.has(t)) continue;
|
||||
if (isArr ? faceSet[t] : faceSet.has(t)) continue;
|
||||
const src = t * 9;
|
||||
outPos.set(srcPos.subarray(src, src + 9), dst);
|
||||
if (outNrm) outNrm.set(srcNrm.subarray(src, src + 9), dst);
|
||||
dst += 9;
|
||||
}
|
||||
} else {
|
||||
for (const t of faceSet) {
|
||||
const src = t * 9;
|
||||
outPos.set(srcPos.subarray(src, src + 9), dst);
|
||||
if (outNrm) outNrm.set(srcNrm.subarray(src, src + 9), dst);
|
||||
dst += 9;
|
||||
if (isArr) {
|
||||
for (let t = 0; t < faceSet.length; t++) {
|
||||
if (!faceSet[t]) continue;
|
||||
const src = t * 9;
|
||||
outPos.set(srcPos.subarray(src, src + 9), dst);
|
||||
if (outNrm) outNrm.set(srcNrm.subarray(src, src + 9), dst);
|
||||
dst += 9;
|
||||
}
|
||||
} else {
|
||||
for (const t of faceSet) {
|
||||
const src = t * 9;
|
||||
outPos.set(srcPos.subarray(src, src + 9), dst);
|
||||
if (outNrm) outNrm.set(srcNrm.subarray(src, src + 9), dst);
|
||||
dst += 9;
|
||||
}
|
||||
}
|
||||
}
|
||||
const geo = new THREE.BufferGeometry();
|
||||
|
||||
Reference in New Issue
Block a user