webcad-ue4-api/CSGSubtract.worker.cjs

157 lines
4.7 KiB
JavaScript
Raw Normal View History

2023-12-07 09:34:41 +08:00
'use strict';
var poly3 = require('@jscad/modeling/src/geometries/poly3');
var booleans = require('@jscad/modeling/src/operations/booleans');
/**
* @param compart true => t2 , false => t1
* @returns 索引
*/
function Max(arr, compart)
{
let best = arr[0];
let bestIndex = 0;
for (let i = 1; i < arr.length; i++) {
let t1 = arr[i];
if (compart(best, t1)) {
best = t1;
bestIndex = i;
}
}
return bestIndex;
}
/** Epsilon used during determination of near zero distances.
* @default
*/
const EPS = 5e-2;
// //////////////////////////////
// tolerance: The maximum difference for each parameter allowed to be considered a match
class FuzzyFactory
{
constructor(numdimensions = 3, tolerance = EPS)
{
this.lookuptable = {};
this.multiplier = 1.0 / tolerance;
}
// let obj = f.lookupOrCreate([el1, el2, el3], function(elements) {/* create the new object */});
// Performs a fuzzy lookup of the object with the specified elements.
// If found, returns the existing object
// If not found, calls the supplied callback function which should create a new object with
// the specified properties. This object is inserted in the lookup database.
lookupOrCreate(els, object)
{
let hash = "";
let multiplier = this.multiplier;
for (let el of els) {
let valueQuantized = Math.round(el * multiplier);
hash += valueQuantized + "/";
}
if (hash in this.lookuptable)
return this.lookuptable[hash];
else {
let hashparts = els.map(el =>
{
let q0 = Math.floor(el * multiplier);
let q1 = q0 + 1;
return ["" + q0 + "/", "" + q1 + "/"];
});
let numelements = els.length;
let numhashes = 1 << numelements;
for (let hashmask = 0; hashmask < numhashes; ++hashmask) {
let hashmaskShifted = hashmask;
hash = "";
hashparts.forEach(hashpart =>
{
hash += hashpart[hashmaskShifted & 1];
hashmaskShifted >>= 1;
});
this.lookuptable[hash] = object;
}
return object;
}
}
}
//并集path2dCsgs 差集 删除小面积结果
function CSGSubtract(geom, path2dCsgs)
{
let gemUnion = path2dCsgs[0];
for (let i = 1; i < path2dCsgs.length; i++)
gemUnion = booleans.union(gemUnion, path2dCsgs[i]);
let newGeom = booleans.subtract(geom, gemUnion);
//删除小面积(只留一个)
{
let fuzz = new FuzzyFactory;
let vmap = new Map;
for (let poly of newGeom.polygons) {
for (let v of poly.vertices) {
let key = fuzz.lookupOrCreate(v, v);
let arr = vmap.get(key);
if (!arr) {
arr = [];
vmap.set(key, arr);
}
arr.push(poly);
v["__key__"] = key;
}
}
let polys = newGeom.polygons.concat();
let polyGroups = [];
let calcs = new Set;
while (polys.length) {
let poly1 = polys.pop();
calcs.add(poly1);
let polyGroup = [poly1];
polyGroups.push(polyGroup);
for (let i = 0; i < polyGroup.length; i++) {
let poly = polyGroup[i];
for (let v of poly.vertices) {
let key = v["__key__"];
let arr = vmap.get(key);
for (let vpoly of arr) {
if (calcs.has(vpoly))
continue;
calcs.add(vpoly);
polyGroup.push(vpoly);
}
}
}
// arrayRemoveIf(polys, poly => !calcs.has(poly)); //加上这个无法提高性能
}
let areas = polyGroups.map(polys =>
{
let area = 0;
for (let poly of polys)
area += poly3.measureArea(poly);
return area;
});
let maxIndex = Max(areas, (t1, t2) => t2 > t1);
newGeom.polygons = polyGroups[maxIndex];
}
return newGeom;
}
addEventListener("message", e =>
{
const [path2dCsgs, geom] = e.data;
try {
const newGeom = CSGSubtract(geom, path2dCsgs);
postMessage({
status: 0,
geom: newGeom
});
}
catch (error) {
postMessage({
status: 1,
error
});
}
});
var CSGSubtract_worker = {};
module.exports = CSGSubtract_worker;
//# sourceMappingURL=CSGSubtract.worker.cjs.map